Skip to content

fix(gateway): harden CORS / Host header / startup safety#1

Closed
YOMXXX wants to merge 1 commit into
feat/claude-code-pluginfrom
fix/gateway-security
Closed

fix(gateway): harden CORS / Host header / startup safety#1
YOMXXX wants to merge 1 commit into
feat/claude-code-pluginfrom
fix/gateway-security

Conversation

@YOMXXX
Copy link
Copy Markdown
Owner

@YOMXXX YOMXXX commented May 18, 2026

Description | 描述

PR Tencent#7 评审过程中扫到 TDAI Gateway HTTP 层有三处 CORS / Host / startup 安全缺陷,独立拆出此 PR 以便 cc 集成 (PR Tencent#7) 与本次安全加固分别评审 / 合并。

This PR hardens three CORS / Host / startup-safety holes in TDAI Gateway surfaced during a security review of PR Tencent#7. Split out so the cc-integration feature and the security fix can land independently.

Depends on | 依赖

⏳ Depends on Tencent#7. src/gateway/cli.ts and src/gateway/__tests__/auth.test.ts are introduced in Tencent#7. Base is currently set to feat/claude-code-plugin; will retarget to main once Tencent#7 lands.

依赖 Tencent#7。本 PR 涉及的 src/gateway/cli.tssrc/gateway/__tests__/auth.test.ts 都是 Tencent#7 引入的文件,base 现在指向 feat/claude-code-pluginTencent#7 合并后将切到 main

Fixes | 修复

1. CORS hardcoded Access-Control-Allow-Origin: * (src/gateway/server.ts:178-180)

handleRequest 无条件下发 Access-Control-Allow-Origin: * + 允许 Authorization 头。README 描述为"默认禁用 CORS",但实际代码无条件启用——与文档矛盾。配合 Tencent#2(Host 不校验)与 Tencent#3(main 入口不走 safety gate)/ Hermes backward-compat no-token 模式,恶意浏览器页面通过 DNS rebinding 可直接调用 daemon 数据端点。

修复:CORS 改为 opt-in:仅当 TDAI_GATEWAY_CORS_ORIGIN 显式设置时才下发对应 Origin 的 CORS 头;OPTIONS preflight 不再默认返回 204,落入正常路由 → Bearer auth 拦截。

2. Host header unvalidated (src/gateway/server.ts:172-174)

req.headers.host 不校验,配合 #1 形成 DNS rebinding 攻击面:攻击者域名短 TTL DNS 重定向到 127.0.0.1 → 受害者浏览器 JS 发起 fetch → daemon 接受。

修复handleRequest 在路由前校验 Host header,剥离端口/IPv6 括号后必须在 {127.0.0.1, localhost, ::1, ::ffff:127.0.0.1} 集合内,否则 403。TDAI_GATEWAY_ALLOW_REMOTE=1 opt-in 时跳过——与 assertSafeHost() 现有 opt-in 语义一致。

3. server.ts main() bypasses cli.ts safety (src/gateway/server.ts:478-499)

tsx src/gateway/server.ts 直跑触发 server.ts 自带的 main()不调用 cli.tsassertSafeHost() + loadTokenFromFile(),导致 host 校验与 token 文件加载被跳过;Hermes backward-compat(无 token)模式下 daemon 裸奔。

修复:抽 assertSafeHost / loadTokenFromFilesrc/gateway/server.ts 作为 export helper(applyStartupSafety)。cli.ts main() 与 server.ts main() 都调用同一段,两条启动路径共用同一段安全门。

Self-test | 自测

  • npx vitest run src/gateway31/31 (扩展自 14/14;+17 新 case 覆盖 CORS opt-in、Host 白名单、TDAI_GATEWAY_ALLOW_REMOTE opt-in)
  • npm run test:cc-plugin -- --run55/55 (no regression)
  • applyStartupSafety() 调用点人工验证:cli.ts main() 与 server.ts main() 均调用

Out of scope | 范围外

PR Tencent#7 评审过程中还发现以下 High/Medium 项,作为 follow-up 单独处理:

  • token-file stat() + readFile() TOCTOU (symlink swap)
  • Stop hook cursor advance 非原子 (capture 成功后 writeCursor 异常 → 下次重发)
  • process.ppid 作为 cc PID(shell wrapper 下不正确)
  • parseJsonBody 无 size limit
  • liveness check 对 PID reuse 不防御

DCO

Commit c0a750eSigned-off-by: 李冠辰 <liguanchen@xiaomi.com>

PR Tencent#7 引入的 Gateway HTTP 层有三处 critical 安全缺陷:

1. CORS 硬编码 Access-Control-Allow-Origin: * 且无条件允许 Authorization 头,
   与 README 描述(默认禁用 CORS)矛盾。
2. handleRequest 不校验 Host header,配合 CORS * 形成 DNS rebinding 攻击面:
   攻击者控制的域名 + 短 TTL DNS → 浏览器 JS 解析为 127.0.0.1 → fetch 通过。
3. server.ts 自带的 main() 入口(`tsx src/gateway/server.ts` 直跑)绕过
   cli.ts 的 assertSafeHost() 与 loadTokenFromFile(),导致 host 校验与 token
   文件加载被跳过;Hermes backward-compat(无 token)模式下 daemon 裸奔。

修复:

- CORS 改为 opt-in:仅当 TDAI_GATEWAY_CORS_ORIGIN 显式设置时下发对应 Origin
  的 CORS 头并 ack OPTIONS preflight;默认状态 OPTIONS 不再绕过 Bearer auth。
- Host header 白名单:handleRequest 前置校验,剥离端口/IPv6 括号后必须在
  {127.0.0.1, localhost, ::1, ::ffff:127.0.0.1};TDAI_GATEWAY_ALLOW_REMOTE=1
  时跳过校验,与现有 assertSafeHost 的 opt-in 语义一致。
- 抽 assertSafeHost / loadTokenFromFile 到 server.ts 作为 export helper
  (applyStartupSafety)。cli.ts main() 与 server.ts main() 都调用同一段,
  两条启动路径共用同一段安全门。

测试:auth.test.ts 从 14 个 case 扩到 31 个,新增 CORS opt-in / Host
白名单 / TDAI_GATEWAY_ALLOW_REMOTE 跳过 的回归矩阵。cc-plugin 测试 55/55
通过无回归。

Signed-off-by: 李冠辰 <liguanchen@xiaomi.com>
@YOMXXX
Copy link
Copy Markdown
Owner Author

YOMXXX commented May 18, 2026

Replaced by upstream-targeted PR — see follow-up that targets Tencent/main directly with CORS + Host fixes scoped to bugs that exist independently of Tencent#7. The server.ts main() bypass (third critical) is intrinsic to Tencent#7's cli.ts split and will be handled within Tencent#7.

@YOMXXX YOMXXX closed this May 18, 2026
@YOMXXX YOMXXX deleted the fix/gateway-security branch May 18, 2026 02:39
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