Skip to content

fix: viewer-server 路径遍历防护 + localhost 认证#4

Open
alloevil wants to merge 2 commits into
mainfrom
fix/viewer-security
Open

fix: viewer-server 路径遍历防护 + localhost 认证#4
alloevil wants to merge 2 commits into
mainfrom
fix/viewer-security

Conversation

@alloevil

@alloevil alloevil commented Jul 8, 2026

Copy link
Copy Markdown
Owner

问题

1. 路径遍历

/api/messages?group=xxx/api/dates?group=xxx 的 group 参数直接拼接到文件路径,虽然过滤了部分字符,但未校验最终路径是否在 OUTPUT_DIR 内。

2. 无认证

/api/sync(触发归档)、/api/browser-login(打开浏览器扫码)、/api/ai-config(写入 AI 配置)这三个敏感端点无任何认证。任何访问 localhost:3456 的人都能触发 Cookie 暴露。

修复

路径校验

  • getGroupDir() 现在用 path.resolve() 校验最终路径是否在 OUTPUT_DIR
  • 路径越界时抛出错误,请求返回 400

localhost 认证

  • 首次启动自动生成 32 字符随机 token,写入 .viewer-token 文件
  • 敏感端点(sync、browser-login、ai-config POST)需 Authorization: Bearer <token>
  • 只读端点(messages、dates、groups、summary)不需要认证
  • Token 注入到 HTML 的 window.__AUTH_TOKEN,前端可用

前端适配

前端 fetch 请求需在敏感操作时携带 token:

const headers = { Authorization: `Bearer ${window.__AUTH_TOKEN}` };

元气小🦐 added 2 commits July 8, 2026 11:16
Security fixes:
- Path traversal: getGroupDir() now validates resolved path stays within
  OUTPUT_DIR, throws on directory escape attempts
- Auth token: auto-generated on first start, stored in .viewer-token file
  - Required for: /api/sync (POST), /api/browser-login (POST), /api/ai-config (POST)
  - Not required for: GET endpoints (messages, dates, groups, summary)
  - Token injected into HTML as window.__AUTH_TOKEN for frontend use
- All write/sensitive operations now require Authorization: Bearer <token>
Extra  after respondUnauthorized function caused node --check to fail.
Caught by CI syntax-check step.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant