Skip to content

fix(mcp): stdio 子进程 env 剥离启动即执行类变量(对称 #137) - #449

Closed
Ver-zhzh wants to merge 1 commit into
huiliyi37:mainfrom
Ver-zhzh:secaudit/mcp-module-20261011
Closed

Ver-zhzh wants to merge 1 commit into
huiliyi37:mainfrom
Ver-zhzh:secaudit/mcp-module-20261011

Conversation

@Ver-zhzh

@Ver-zhzh Ver-zhzh commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

修复批次:MCP stdio 子进程 env 硬化(对称 #137)

背景:2026-10-11 安全审计(mcp 子系统,PLAYBOOK §6 默认行为)挖出。MCP stdio 子进程的 env 由 server 配置(用户配置/技能/配置同步等可写来源)原样组装,而审批指纹刻意不绑定 env 键值(凭据轮换容忍)——仅改值不触发重审。与 src/tools/bash.ts 在 issue #137 已剥离 NODE_OPTIONS/JAVA_TOOL_OPTIONS 不对称。

1. 配置可控的 env 值可在 MCP stdio 子进程启动时执行任意代码

现象:mcpServerFingerprint 只取 envKeys: Object.keys(cfg.env).sort()(server-approval.ts:113-122);buildStdioChildEnv 把配置 env 原样并入子进程 env(stdio-env.ts)。探针实证:同键集、值从 tok_ORIGINAL 改为 tok_ATTACKER → 指纹逐字节相同;NODE_OPTIONS=--require <hook> 随 env 进子进程并被 Node 执行(marker 文件落盘)。
根因:审批指纹的「值不参与」是刻意设计(容忍凭据轮换),真正的缺口是 env 组装处未像 bash 路径(#137)一样剥离启动即执行类变量。
修复:src/mcp/stdio-env.ts 新增 stripCodeExecEnvVars,在 buildStdioChildEnv 组装最终 env 时显式剥离 NODE_OPTIONS、JAVA_TOOL_OPTIONS、_JAVA_OPTIONS、JDK_JAVA_OPTIONS、LD_PRELOAD、DYLD_INSERT_LIBRARIES(大小写不敏感)。指纹逻辑不动,凭据轮换容忍保留。

未修观察(如实报告,非本批引入)

  • 同一文件基座的 buildStdioEnvWithNodePath 另被 src/lsp/multi-manager.ts 复用(LSP 子进程同类威胁面),本轮按最小改动原则未动,留待 LSP 模块审计时处理。
  • 审计其余面均无 finding:resolve-node-cli.ts args 逐字进 argv(无 shell、无穿越)、工具清单持久化已 fail-closed(名+hash、变更双态 block)、待批登记 payload 仅含 env 键名。

验证

项 结果
tsc --noEmit 0 新增报错
stdio-env / transport-factory / resolve-node-cli 单测 41/41 通过(含 4 个新回归用例)
攻击探针(NODE_OPTIONS=--require 恶意 hook) 修复前:子进程执行 hook;修复后:变量被剥离、hook 未执行

CI 说明(基线预存失败,非本批引入)

  • CLI frontend 三平台(ubuntu/macos/windows)全绿。
  • windows-smoke 与 ci (24) 红项已与干净上游 main(run 38137254300,abb7628)逐项核对,失败集合完全一致,均为上游基线预存:
    • publish-release-catalog「release v3.30.0 缺少 manifest 引用的资产」
    • release DRY RUN / AtomGit 告警 / old publishers 替换 pinned stable catalog
    • max-lines ratchet(点名文件:env-registry.ts、schema.ts、serve.ts、read-file.ts——均非本批改动文件)
    • architecture guards、startup memory(RSS 128MB)、capsule-recall 系列

@sky-mirrors sky-mirrors left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

独立复验通过 ✅

在 origin/main @ abb7628 上套用本 PR diff 实测:

  • 专项测试:src/mcp/__tests__/stdio-env.test.ts 15/15 通过(160ms,4 个 suite);
  • 回归:renamed-node-mcp.test.ts 5/5(含 win32 重命名 runtime 的生产 npx MCP 握手端到端)。

实现核验:CODE_EXEC_ENV_VARS 清单(NODE_OPTIONS / JAVA_TOOL_OPTIONS / _JAVA_OPTIONS / JDK_JAVA_OPTIONS / LD_PRELOAD / DYLD_INSERT_LIBRARIES)大小写不敏感剥离,覆盖 win32 场景;注释把动机写得很清楚——审批指纹刻意不绑 env 键值(凭据轮换容忍),env 因此是免审通道,必须在此显式净化,与 bash 侧 #137 硬化对齐。transport-factory.ts 的 buildStdioChildEnv 接线确认到位。

与 #452(hooks 侧对称净化)同批收编效果最佳。可收编。

@huiliyi37

Copy link
Copy Markdown
Owner

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

本 PR 的改动(fix(mcp): stdio 子进程 env 剥离启动即执行类变量(对称 #137))已经 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>
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.

3 participants