MCP 调试器被曝 OAuth 代码执行风险
据摘录披露,MCP Inspector 在 Windows 和 WSL 上的 OAuth 握手流程存在代码执行风险,远程 MCP 服务可在没有模型参与或工具调用的情况下触发。标题还提示常规 npm 更新可能遗漏修复,但摘录未给出受影响版本及修复路径。
AI 深度解读
用来检查陌生 MCP 服务的工具,自己先被陌生服务攻破了。原文拆解的 CVE-2026-119025,问题出在 MCP Inspector 的 OAuth 登录流程:Windows 和 WSL 上,服务端提供的登录地址可能被送进 PowerShell 执行,整个过程不需要模型参与,也不需要调用工具。
对程序员更有用的提醒是:Agent 权限规则管不到所有连接代码,而反复运行 npm update,也可能始终装不到修复版本。漏洞卡在了协议、依赖包与操作系统之间。
只是打开登录地址,为什么会变成执行代码
MCP Inspector 是 Model Context Protocol 的官方调试工具,AWS、Cloudflare 和 Azure 的文档都会引导开发者用它测试远程 MCP 服务。原文援引 Pillar Security 的数据,称它每周约有 768,000 次 npm 下载。它的使用场景,恰好包括连接尚未建立信任的服务。
攻击链从一次正常的认证响应开始:远程服务返回 401 和 WWW-Authenticate,再提供 OAuth 发现文档。文档里的 authorization_endpoint,也就是浏览器应该打开的登录地址,由服务端决定。
Inspector 通过 npm 包 open 自动打开地址。交互式终端默认开启这个行为,CLI、TUI 和 Web 客户端三处都有相关调用。
问题出在 Windows 和 WSL 的实现分支。open 10.x 把 URL 放进 PowerShell 双引号字符串,再进行 base64 编码,通过 -EncodedCommand 执行,却没有正确转义 URL。base64 只是编码,不会让字符串失去代码含义。
原文用下面的地址演示:一个合法 HTTPS URL,如何夹带写文件操作。
https://evil.test/$([IO.File]::WriteAllText('C:\Users\Public\pwned.txt','RCE'))
要看的是 $([IO.File]::WriteAllText(...)):PowerShell 会在双引号字符串里计算 $() 子表达式,于是打开网址变成了以当前用户权限写文件。
URL 序列化会编码空格和双引号,却保留 $ ( ) [ ] : , + & 等字符,这个载荷无需依赖那些会被编码的字符。执行发生在连接阶段,甚至还没列出任何工具。
HTTPS 检查和 Agent 审批为什么都拦不住
地址符合 HTTPS 格式,不代表它能安全地进入命令解释器。
这条链里的地址可以通过协议检查。真正阻止该载荷的是 open 11:它转义参数,并使用 PowerShell 单引号字符串,让 $() 保持为普通文本。限制 URL 协议仍有价值,但不能代替命令参数处理。
Agent 的审批规则也没有介入机会。这里没有模型决策,没有工具调用,自然不会触发针对工具执行的授权。故障发生在 Agent 下面一层:客户端处理连接和认证的代码。
信任还可能在连接之后变化。载荷来自每次请求收到的发现文档,所以即使最初添加的是正常服务,域名过期或服务后来被入侵,也可能产生相同后果。原文还提到仿冒包名这一入口。
证据边界要分清:研究者演示了危险字符串在 PowerShell 中执行;Windows、WSL 上连接路径的可达性,则由 win32 分支代码审查确认。原文没有报告真实环境中的利用事件,不能把它写成已经发生的大规模攻击。
按原文时间线,公告 GHSA-q978-78c7-phqw 于 10 月 21 日发布,CVSS 3.1 为 8.8;CVE 记录于 10 月 29 日发布,CVSS 4.0 为 7.7;Pillar Security 于 11 月 5 日发布 Inspector 专项分析。两套评分属于不同版本体系,不应直接拿分数变化判断风险升降。
为什么更新过依赖,漏洞还可能留在电脑里
CVE 记录列出的受影响范围是:
open >= 7.2.0且< 11.0.0。@modelcontextprotocol/inspector >= 2.0.0且< 2.12.0。- 同样携带这条链的
opencode-ai >= 1.0.137且< 1.18.33。
这条 PowerShell 攻击链针对 Windows 和 WSL。macOS、Linux 分支通过 spawn 的参数数组调用系统打开程序,没有经过 shell,因此不存在同一条执行路径。
升级陷阱藏在 Inspector 的三个依赖清单里:它们都写着 "open": "^10.2.0"。插入符范围不会跨越主版本,所以 npm update 仍会把依赖留在 10.x,无法自动进入修复所在的 11.x。
维护者需要主动升级到 open 11.0.4,并增加 overrides,防止 Web 客户端的传递依赖继续保留旧版。原文给出的检查命令,用于查看实际解析出的依赖:
npm ls open @modelcontextprotocol/inspector
要看输出里的实际版本,以及是否存在多份 open;package.json 中写下的意图,并不等于安装结果。
修复边界还不能只记一个 2.12.0。原文称,11 月 4 日发布的 Inspector 2.14.0 又修复了三个影响 2.13.0 及以下版本的问题:MCP App 沙箱页面导航后,代理仍继续转发;导入 server.json 时,未经验证的运行参数可能进入 npx、uvx 或 docker run,而界面只展示正常包名;服务端的 outputSchema.pattern 还可能在工具调用后引发正则表达式拒绝服务(ReDoS),卡住界面。
另外,Inspector v1 曾有跨平台漏洞 GHSA-4fc4-wcmh-4g86,评分 9.6,OAuth 回调查询参数可让远程会话转入本地 stdio 命令执行,修复版本是 1.0.3。不能因为自己用 macOS,就跳过版本检查。
我的判断
作者最有价值的判断,是把调试器也放回攻击面里。处理未知服务返回的 URL、配置和 schema,本来就在处理不可信输入;界面上尚未出现「执行工具」,不代表本地程序还没做敏感操作。
但原文没有给出隔离方案的对照测试,也没有量化团队实施成本。用容器或一次性虚拟机测试陌生服务,是合理的风险控制建议,不是经过本文实验验证的收益结论。Windows 主机上的 Linux 容器可以避开这条 PowerShell 分支,也不能据此认定其他输入处理问题一并消失。
对依赖管理,也不必推导成「插入符范围都不该用」。锁定版本有利于复现,却同样可能锁住漏洞。更实用的区别是:常规更新负责范围内升级,安全修复还需要核对公告、跨主版本变更和实际依赖树。
这次失守的是把远程字符串交给操作系统执行的边界,Agent 审批无法替这一层兜底。
能拿来做什么
- 如果在 Windows 或 WSL 上测试陌生 MCP 服务,按原文建议使用隔离环境,并核对 Inspector 至少为
2.12.0;涉及server.json导入时,对照原文升级到2.14.0。使用opencode-ai的项目也要检查是否达到1.18.33。 - 如果 Node 工具会把远程返回的 URL 交给
open(),检查实际依赖树是否仍有低于11.0.0的版本,尤其留意传递依赖。修复验收应包含 lockfile 和安装结果,不能只记录执行过npm update。 - 审查 AI 编程工具时,把自动打开浏览器、导入配置和启动本地进程一起纳入检查。对曾在 10 月用 Windows 连接过如今不再可信服务的情况,原文建议按不可信代码暴露排查计划任务、注册表 Run 键和 SSH 授权密钥;这属于暴露后的检查建议,不能直接当作已被入侵的证据。