深海军蓝背景上的一幅生成式抽象插画:左侧一个小的琥珀色服务器立方体发出一条细细的青色线条,由类似字形的形状组成,直线穿过一道高耸的半透明蓝色玻璃膜,继续延伸到右侧一块深色终端面板,那里有一个琥珀色光标块在发光。线条连续不断。画面中没有文字、人物或组织标志。OrcaRouter 标志合成在右下角。
AI Safety Incidents

OpenCode 的 MCP 登录功能将服务器 URL 交给了 PowerShell——却没有任何 CVE 可用来标记这一问题

作者

Magnus Corvin

发布日期

最新模型 · 20查看全部模型 →
基准测试:Artificial Analysis · 每日更新
返回全部文章

,2026年10月19日Pillar Security 披露了 OpenCode 中的一个远程代码执行漏洞。OpenCode 是由 Anomaly 维护的开源编码智能体:开发者配置的一个远程 Model Context Protocol 服务器可以在 MCP OAuth 登录过程中于该开发者自己的机器上运行任意代码,期间没有任何同意提示。该漏洞仅限于 Windows 和 Windows Subsystem for Linux,在这些平台上,OpenCode 将服务器提供的登录 URL 交给 PowerShell 命令时未做转义。Pillar 将受影响范围定为 1.0.137 至 1.18.32。Anomaly 在 1.18.33 中修复了该问题,于 2026年9月28日发布到 npm,且未申请 CVE,也未发布安全公告——因此常规漏洞情报源中不会有任何信息提醒受影响团队升级。Pillar 表示没有证据表明该漏洞曾被用于攻击。这是 AI 事件档案 中的一条记录,其中每条记录都附有自己的来源、严重程度、置信度评级和争议标记。

这个缺陷实际上是什么

当 MCP 客户端连接到希望获得授权的远程服务器时,它会运行 OAuth 发现握手。服务器以 401 和指向其发现文档的质询作为响应,而这些文档中的一个字段——authorization_endpoint——会告诉客户端将用户发送到哪里登录。它是一个自由格式字符串,而被认证的一方正是选择它的一方。

在 OpenCode 1.18.32 中,那个字符串从网络传输一路进入了 shell。Pillar 追踪了这条路径:从服务器的发现文档出发,经由 MCP SDK 进入 oauth-provider.ts、mcp/index.ts 和 browser.ts,最终到达 open,这是 OpenCode 用来启动浏览器的小型包。该路径上没有任何环节检查 URL 的 scheme,也没有任何环节将其与开发者所配置服务器的 origin 进行比较。该握手在设计上就是自动的——其全部意义在于把你送到登录页面,而无需你复制 URL——因此,在服务器的应答与启动器之间不存在任何批准步骤。

The launcher is where it broke. On macOS and Linux, open passes the address as an argument vector and no shell is involved. On Windows, version 10.1.2 of open — the version every affected OpenCode release pinned — builds a PowerShell command, base64-encodes it and runs it with powershell -EncodedCommand. Pillar quotes the source: the application name is escaped on one line, and the target URL is not. PowerShell evaluates $(...) subexpressions inside double-quoted strings, so an address of the form https://evil.test/$([IO.File]::WriteAllText('C:\Users\Public\pwned.txt','RCE')) runs before the browser launch fails. OpenCode discards that failure.

有两个特性使其容易被忽视。有效载荷中不包含空格,因此 URL 规范化会使其保持原样,而且它在语法上是一个普通的 https 地址。而且,服务器在被配置时并不一定具有恶意:Pillar 指出,后来的入侵、被劫持的注册表条目、误植域名或过期域名,都会将受信任的配置条目变成投递机制。

谁被曝光了

暴露人群是运行 OpenCode 且配置了远程 MCP 服务器的 Windows 和 WSL 用户。Pillar 称 OpenCode 的每周 npm 下载量约为300 万次,并拥有 21.1 万个 GitHub 星标;Infosecurity Magazine 的报道称其星标数超过 21.8 万。这两个数字都不是受影响安装数量的统计,且尚未有人公布此类数字。

触发点是两个主要说法出现分歧的唯一一点,这对风险和严重性都很重要。Pillar 将利用描述为不需要额外的用户交互或同意。The Hacker News 在其 10 月 22 日的报道中称,浏览器步骤仅在开发者通过运行opencode mcp auth或发出匹配请求来启动登录时才会执行,而仅仅配置了服务器或打开会话并不会走到这一步。无论哪种情况,开发者都没有做任何不寻常的事;对已在配置中的服务器启动身份验证是常规操作。但“无交互”和“一次常规交互”是不同的说法,这一差异会直接影响评分。

这个修复是以重构的名义交付的。

Pillar 通过 GitHub Security Advisory 私下报告了该漏洞,报告时间为 2026 年 8 月 29 日,并提供了完整复现材料。随后在 9 月 25 日,其又在安全公告线程之外跟进;Anomaly 确认报告已送达其团队,并回复称恶意 MCP 服务器不在其威胁模型范围内。同日,拉取请求 #51414——以提交 29f07e0c 合并——已落地。据描述,该请求将八个浏览器启动调用点整合到一个辅助函数中。三天后,即 9 月 28 日,版本 1.18.33 发布到了 npm。

该补丁有三层。开放依赖项已移至 11.0.4,它会把目标用单引号包裹起来,而 PowerShell 不会展开单引号内的任何内容。新增的 openUrl() 辅助函数会拒绝非 HTTP(S) 方案。一项方案检查被加入 redirectToAuthorization 本身,也就是 Pillar 在其报告中指出的边界处。无论是拉取请求还是发布说明,都没有提到安全缺陷,且 Anomaly 未申请 CVE。

The Hacker News 报道称,Anomaly 公开发布的安全政策指出,用户配置的 MCP 服务器“在我们的信任边界之外”,并且该公司今年已针对其他 OpenCode 代码执行漏洞发布安全公告,其中包括一个在 8 月修复的漏洞。Pillar 对所收到回复的描述更为直白:“我们已经更新了依赖项,但一般来说,试图应对恶意的 MCP 服务器超出了我们的威胁模型。”

An HTML timeline card titled 'How a five-year-old escaping bug reached OpenCode', subtitled 'Dated entries from Pillar Security's report and the open package's own issue history', listing nine rows: 22 October 2020, open issue #202 reports that a URL containing a dollar sign breaks on WSL 2; 18 October 2023, issue #323 titles 'OS command injection on windows when opening urls'; 9 July 2025, CVE-2025-6514 in mcp-remote, same sink, CVSS 9.6; 15 November 2025, open 11.0.0 quotes the PowerShell target; 7 December 2025, OpenCode calls open() with a server-supplied URL; 29 August 2026, Pillar reports privately via GitHub Security Advisory; 25 September 2026, pull request #51414 merged; 28 September 2026, OpenCode 1.18.33 published to npm, no CVE and no advisory; 19 October 2026, Pillar publishes. A footer cites Pillar Security and the open repository.

按时间顺序来看,这条时间线把 OpenCode 的这个 bug 放在一条长达五年的轨迹的终点,而不是起点。制造出它的缺陷早已公开,其修复也早已发布,而使用它的那行代码当时尚未被写下。

为什么方案校验不会阻止它

针对这类 bug,公认的补救措施是进行 URL scheme 校验:阻止奇怪的 scheme,允许 http 和 https,到此为止。这正是 MCP TypeScript SDK 所提供的方式,也是 OpenCode 在 1.18.33 中加入的方式。Pillar 的 payload 能通过其中每一项检查,因为它是 https。SDK 的拒绝列表会阻止 javascript:、data: 和 vbscript:;更严格的 http/https 允许列表曾在 2025 年 8 月的 SDK 拉取请求 #841 中提出,但未合并便关闭了;而拉取请求 #877 在 v1.17.4 中发布了包含三种 scheme 的拒绝列表——Pillar 称,在其发布时,这仍是 SDK 1.32.0 中的策略。真正堵住 OpenCode 漏洞的是依赖升级,而不是那些看起来像安全修复的检查。

历史表明,不应把这当作某一个项目的疏忽。自 2021 年以来,open 包一直在 README 中警告称,它不提供任何安全保证,清理输入是调用方的责任。2020 年 10 月,一名用户提交了 issue #202,报告在 WSL 2 上,包含美元符号的 URL 会丢失自身的一部分——这是字符串展开问题,当时是作为断链小麻烦提交的。2023 年 10 月,一名 Adobe 工程师提交了 issue #323,“在 Windows 上打开 URL 时的操作系统命令注入”,并附上一行概念验证:open('https://$(calc.exe)')。维护者引用了 README,并表示欢迎提交改进转义的拉取请求;该 issue 被以“不计划处理”关闭,而三天后,open 11.0.0 还是于 2025 年 11 月 15 日发布了转义处理。OpenCode 于 2025 年 12 月 7 日编写了其浏览器启动调用,此时 open 的修复版本已存在三周,而它针对的固定版本却已经过时数月。

在撰写那份呼吁之前的几个月里,MCP 生态系统在同一个 sink 或同一个字段上记录了三起 CVE:CVE-2025-6514 出现在 mcp-remote(CVSS 9.6,由 JFrog 于 2025 年 7 月 9 日披露)、CVE-2025-58062 出现在 openmcp-client,以及 CVE-2025-10619 出现在 sequa-mcp。Pillar 的对比对象是从完全不根据远程字符串构建 shell 命令的客户端:它点名 gemini-cli、Claude Code、github-mcp-server 和 Docker 的 mcp-gateway 是将 URL 作为参数向量传递,这使得字符串内容是什么的问题不再具有关键影响。

A generated abstract illustration on a dark navy field: a long cyan ribbon of abstract glyph shapes runs left to right and splits in two at a hollow chrome ring, which the upper branch passes straight through while the lower branch curves downward into a glowing amber terminal rectangle at bottom right. A faint dotted outline of an empty browser window floats in the upper right. No text, people or organisation logos appear. The OrcaRouter logo is composited in the bottom-right corner.

哪些是已确立的,哪些不是

该记录被档案馆评为置信度 A,其背后的报道也经得起检验。Infosecurity Magazine 于 10 月 20 日刊发了对 Pillar 的 Eilon Cohen 的专访;The Hacker News 于 10 月 22 日发表了自己的报道;丹麦国家 CERT——DKCERT 于 10 月 21 日援引 Infosecurity 总结了这一发现;云安全联盟的研究实验室发表了一篇分析,补充了下方唯一一项实质性保留意见。这些都不是报告方,且它们在机制、受影响版本和静默修复上说法一致。Anomaly 本身未就该漏洞发布任何内容。

已确立,并记录在案:

• 缺陷、其机制及其平台范围。Pillar 指出了具体的源代码行,修复在公开的 1.18.32 至 1.18.33 差异中可见;两篇独立的新闻报道描述了相同的数据流。

• 受影响版本范围为 1.0.137 至 1.18.32,修复版本为 1.18.33,发布于 2026 年 9 月 28 日。

• 不存在 CVE,也不存在任何安全公告。这一点是可以核查的,而且对防御方而言是起支撑作用的关键事实。

• 也就是没有报告过任何利用情况。Pillar 表示未发现其在攻击中被使用的迹象,The Hacker News 也指出未公布任何沦陷指标。未公布指标并不等于不存在,而在缺少厂商遥测数据的情况下,这两种解读都无法得到证实。

未建立,或存在冲突:

• 9.8。这个数字是 Pillar 提出的 CVSS v3.1 评分,并非官方评分:由于没有 CVE,就不存在 NVD 评分,也没有厂商评分。云安全联盟(Cloud Security Alliance)的研究说明指出,9.8 假设无需用户交互;如果 The Hacker News 对触发条件的描述属实,那么要求用户交互的评级——约为 8.8——会更合适。本文并不对此下定论;该档案自身的高危标签是一种分类,而不是评分。

• 发布日期。Pillar 的报告在页眉中标注日期为 2026 年 10 月 19 日,两篇新闻报道均采用该日期;但 Pillar 自己报告底部的披露时间线将发布日期列为 10 月 4 日。档案记录为 10 月 19 日,精确到日。

• 受影响用户群体的规模。目前尚未公布具体数量。上文的下载量和星标数均为仓库指标,并非安装量。

• 是否有任何机器确实遭到入侵。已公开的内容并不支持这一点,而且记录中也没有任何实际损害的记载。

An HTML card titled 'Established, and not', split into two columns. The left column, headed 'Established', lists: affected versions 1.0.137 to 1.18.32, Windows and WSL only; fixed in 1.18.33 on 28 September 2026; no CVE and no security advisory issued; no exploitation reported and no indicators published. The right column, headed 'Not established', lists: official severity, since 9.8 is Pillar's proposed score with no CVE to attach it to; the publication date, 19 October in the report header and 4 October in its own timeline; the number of exposed installations; whether any host was compromised. A footer cites Pillar Security, The Hacker News and the Cloud Security Alliance research note.

有哪些变化,以及该怎么做

修复办法是进行版本检查,因为除此之外没有任何办法能告知你。OpenCode 1.18.33 或更高版本已修复。受影响的安装必须通过直接清点软件包来发现:Pillar 的建议是直接清点 OpenCode 本身,而不是等待信息源,而 Cloud Security Alliance 的说明建议查询 opencode-ai 软件包的版本,因为没有可供信息源匹配的标识符。无法升级且运行 Windows 或 Windows Subsystem for Linux 的团队,应从其 OpenCode 配置中移除未经审核的远程 MCP 服务器;opencode mcp list 可显示存在哪些服务器。

对于维护 MCP 客户端的人来说,Pillar 的指导比通常的建议范围更窄:将 URL 作为参数向量传递,绝不要根据远程字符串构建命令行;将 OAuth 发现绑定到用户所配置服务器的源,并将发现文档、服务器元数据和工具描述符视为不可信输入,而不是设置。云安全联盟的说明补充了威胁狩猎启发式——一个 OpenCode 进程启动 powershell.exe并带有 -EncodedCommand,就是一个例子——同时强调这些是检测工程建议,而非已公布的入侵指标。

不是 Console 泄露事件

Pillar 的披露发生在 Anomaly 确认 OpenCode 托管 Console 遭遇另一起入侵的几天后,该入侵可能暴露了已存储的 API 提供商密钥。这两起事件并无关联,Pillar 的 Eilon Cohen 在接受 Infosecurity Magazine 采访时明确说明了二者的区别。“这起入侵影响的是一个位于托管密钥代理之后的遗留系统,并暴露了用户存储在那里的提供商密钥,”他说。“我们报告的漏洞则恰恰相反:一个恶意的远程 MCP 服务器在 OAuth 握手期间在开发者自己的机器上执行代码。目标对象和攻击者所处位置都不同。”Console 入侵是档案中的另一条独立记录,二者应作为两个独立条目来看待。

在科恩的框架中,把二者联系起来的是它们共同背后的那个问题:“你让谁把凭据和输入交给 AI 编程工具,以及该工具会拿它们做什么。”

披露缺口才是比漏洞本身更持久的部分。一个被其发现者评为严重级别的缺陷,在一次依赖版本升级中被修复,却不出现在防御者通常依赖的任何自动化信号里,这就使得直接清点资产成为唯一的检测方法——而厂商并未发布任何公告告知任何人去执行清点。