深海军蓝背景上的抽象技术插图:一个半透明盒子左壁上发光的输入端口接收一条细而浅色的线,这条线上没有徽章,也没有钥匙。盒子内部,这条线与一叠小圆角面板相接,并分叉成一短排带有棱角、类似命令的笔画,向下进入下方隔间;下方隔间里聚集着一簇发光的钥匙形令牌。输入端口旁边还有第二道关着的门,用浅蓝色描边。没有文字,没有人,也没有组织标志。
AI Safety Incidents

一次未认证的 POST 请求发往 Bifrost 管理 API,以网关用户身份启动了一个命令

作者

Magnus Corvin

发布日期

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

2026 年 9 月 14 日,JFrog Security Research 发布了 CVE-2026-90898,这是 Bifrost 中的一个命令执行漏洞;Bifrost 是由 Maxim 维护的开源 AI 网关。该漏洞被评为 9.8 分(满分 10 分)。攻击只需一个 HTTP 请求。未经身份验证的 POST /api/mcp/client 会注册一个 stdio MCP 客户端,Bifrost 会将其解析为程序名加参数列表,并在任何 MCP 握手之前,立即以运行该网关的用户身份启动它;在官方镜像上,该用户是 appuser。网关也是运营者的提供商密钥和虚拟密钥所在之处,因此在那里运行的进程能够接触到凭据。让该请求能够匿名发起的是一个随附默认设置:governance.auth_config.is_enabled 为 false,而且用 JFrog 的话说,“关闭认证意味着每个调用者都是本地管理员。”没有所引用的来源报告该漏洞曾被利用。该记录自身的来源、严重性评级和置信度评估收录在 AI 事件档案 中,与过去一年其他有记录的 AI 网关和 MCP 漏洞并列。

Bifrost 是一个单一服务,位于应用程序与其调用的语言模型之间。其代码仓库将其描述为一个开源、采用 Apache-2.0 许可证的网关,“通过单一的 OpenAI 兼容 API 统一访问 23+ 家提供商……”,其功能包括 MCP 代理、虚拟密钥、预算以及按提供商进行负载均衡;截至 2026 年 10 月 28 日,它拥有约 9,150 个 GitHub 星标。正是这种组合,使得在这台特定主机上获得一个 shell 值得被评为严重级别:负责路由请求的进程,同时也是持有其路由到的每个上游服务凭据的进程。《Hacker News》在 9 月 22 日报道该漏洞时直白地指出了后果——由于该网关存储了每个已连接提供商的 API 密钥,在网关进程上执行命令就会让攻击者获得这些凭据的访问权限。

整个攻击只是一次 POST 请求

JFrog 的安全公告(参考编号 JFSA-2026-001686326)描述了一个端点,该端点用于让管理员添加 MCP 服务器。MCP 规范中的 stdio 客户端不是 URL;它是一条命令及其参数,宿主程序应负责启动它。Bifrost 通过管理 API 接受该配置,并在添加客户端后立即启动程序。无需先成功完成能力协商、服务器身份检查或握手——公告明确指出,启动该进程的并不是握手。

该公告中的概念验证是一个简短的 JSON 请求体,被发送到某个网关,而该网关的身份验证仍保持默认设置。它注册了一个客户端,其命令为 /bin/sh,参数用于写入一个标记文件,随后再读回该标记。JFrog 补充了一个在事件响应期间至关重要的操作细节:当 Bifrost 等待一个永远不会到来的握手时,该 HTTP 请求可能会超时,而日志中的超时并不意味着命令未能启动。到那时,该进程早已在运行了。

该 CVE 记录由作为 CVE 编号管理机构的 JFrog 分配,将该缺陷映射到 CWE-306,即关键功能缺少身份验证,以及 CWE-284,即访问控制不当,并指出了承载处理程序及其中间件的两个文件:transports/bifrost-http/handlers/mcp.go 和 transports/bifrost-http/handlers/middlewares.go。受影响的模块是 github.com/maximhq/bifrost/transports,在 Linux 和 macOS 上,影响低于 2.1.0 的所有版本。

使该请求匿名的默认设置

如果没有第二个条件,这一切都无法被利用,而第二个条件正是产品自身的默认配置。Bifrost 的管理认证中间件受 governance.auth_config.is_enabled 控制,而该项默认值为 false。关闭它时,中间件会将每个调用者都视为本地管理员——公告自身的总结是,关闭认证意味着每个调用者都是本地管理员——因此,本应阻止该请求的检查根本不在处理路径中。

该修复(拉取请求 #6757)于 2026 年 9 月 2 日合并到项目中,比该 CVE 公布早十二天,比包含该修复的版本发布早六天。其描述对问题的形态异常坦率:该拉取请求在同一注册 API 中封堵了两个未认证访问原语,而不是一个。第一个是 stdio 客户端。第二个是指向环回或私有网络地址的 http 或 sse MCP 客户端,该请求将其称为针对内部服务的 SSRF 原语,“包括 169.254.169.254 云元数据端点”。现在,当请求在没有真正凭据检查的情况下到达处理程序时,两者都会被以 HTTP 403 拒绝。经过身份验证的管理员保留这两项能力,运维人员仍可通过 config.json 配置 stdio 客户端。

第二个原语并未出现在 CVE 文本中。它出现在补丁里,也正是这个修复采用门控而非移除方式的原因:该特性本身从来都不是缺陷,把未认证的调用方当作管理员才是。

管理 API 实际监听的位置

可达性是记录中各来源描述得最一致、却最少被测量的部分。JFrog 的公告称,原版二进制默认监听 localhost:8080,这会将攻击者限制在主机本身。同一团队针对伴生漏洞的公告指出,官方 Docker 镜像反而绑定 0.0.0.0,The Hacker News 也重复了这一说法:如果发布了端口,该镜像会使管理 API 可从容器外部访问。Bifrost 自己的 README 快速入门运行“docker run -p 8080:8080 maximhq/bifrost”,而 Docker 的 -p 会在未指定地址时把容器端口发布到所有主机接口上。该漏洞的 GitHub 公告记录称,所报告的路径已针对已发布的 maximhq/bifrost:latest 镜像进行验证;在该镜像中,一个未经身份验证的请求启动了 /bin/sh,并以 appuser 身份写入了一个标记。

任何来源都没有提供的,是一个数字。没有面向互联网的 Bifrost 实例数量,没有扫描结果,没有遥测数据,也没有受害者。记录中并未体现真实危害,而这种缺失是关于报道本身的事实,而非一种安慰——这类漏洞只有在两个条件同时满足时才危险:一个暴露的监听器和一个未被改动的默认值,而没有人公布过它们同时出现的频率。

一个端点,两个缺陷,一个根本原因

在 MCP 安全公告发布八天前,即 2026 年 9 月 6 日,同一研究团队发布了 CVE-2026-86242,这是进入同一进程的第二条未认证路径。该漏洞由 Or Peles 发现,评分为 8.1,利用的是 POST /api/plugins:Bifrost 会接受一个已启用的自定义插件,而其路径是一个 HTTP URL;共享对象加载器会将 http 前缀的路径视为下载,将响应体写入临时 .so 文件,并将该文件交给 Go 的 plugin.Open。如果加载成功,一个可选的 Init 函数会立即以攻击者的配置、以网关用户身份运行。

构建类型决定了攻击者能获得什么。在项目文档中针对自定义 Go 插件说明的动态链接构建上,加载预期会成功,安全公告将其称为未经身份验证的远程代码执行。在已发布的静态链接 Docker 镜像上,plugin.Open 会失败并提示“Dynamic loading not supported”,因此同一请求降级为服务端请求伪造。可加载的插件还必须与主机的 Go 版本、操作系统、架构和链接方式匹配,这是实实在在的约束,而非形式上的要求。修复版本为 transports/v2.0.0,通过拉取请求 #5763 引入,受影响范围是低于该版本的所有版本。

陷阱在于发布顺序。v2.0.0 修复了插件路径,却没有修复 MCP 路径——The Hacker News 明确指出了这一点,而 JFrog 的 MCP 安全公告也确认,v2.0.0 仍然允许未经身份验证的 stdio 注册。对于一名在 9 月 6 日安全公告发布后及时打了补丁的运维人员来说,仅就这一点而言,在 transports/v2.1.0 于 9 月 8 日发布之前,其系统仍然处于暴露状态。两个漏洞都可归结为两份安全公告以及厂商自家拉取请求中的同一句话:默认配置为禁用身份验证。

这些来源能确立什么,不能确立什么

机制、版本范围、修复方案和致谢信息在安全公告、JFrog 分配的 CVE 记录、项目自身的拉取请求和发布说明,以及 The Hacker News 的报道中是一致的。剩下的分歧在于严重程度,而且这一分歧确实存在。

9.8 是 JFrog 作为分配 CNA 给出的评分,也是 NVD 所采用的评分——NVD 记录将 reefs@jfrog.com 列为指标来源,并且截至 2026 年 10 月 28 日,该条目仍显示为“等待分析”状态,这意味着 NVD 发布的是分配方的向量,而非其自身对该向量的分析。CISA 协调员附在同一记录上的 SSVC 评估(时间戳为 2026 年 9 月 14 日)显示利用情况为“无”、可自动化为“是”、技术影响为“完全”。FIRST 的 EPSS 模型在 2026 年 10 月 27 日给出的未来 30 天内遭利用概率为 2.3%,在所有已评分 CVE 中处于第 83 百分位;并且无论是此 CVE 还是 CVE-2026-86242,都未出现在日期为 2026 年 10 月 27 日的 CISA 已知被利用漏洞目录中。

对此,Maxim 对该评级提出异议。该公司首席技术官兼联合创始人 Akshay Deo 在向 The Hacker News 发表的声明中表示,实际风险低于该严重性评分所暗示的程度,因为利用该漏洞需要管理界面可从不受信任的网络访问,并且操作员未设置身份验证;他表示,默认且有文档记载的部署方式会将网关置于专用网络内部。The Hacker News 报道称,Maxim 认为该漏洞严重性低,并正与分配该 CVE 的 JFrog 合作修订评估。该声明仅出现在那一家媒体;未发现第二家出版物引用 Maxim 的立场,且截至 2026 年 10 月 28 日尚未发布任何修订——CVE 记录最后更新于 9 月 14 日,NVD 条目更新于 9 月 18 日,二者仍为 9.8。

还有两处缺口值得明确指出,而不是一笔带过。该项目的 GitHub 安全公告发布于 2026 年 9 月 23 日,并将 JFrog 的研究员列为报告者,但其中仍将 MCP 漏洞评为 9.8、将插件漏洞评为 8.1,没有任何迹象显示存在 Maxim 所述的那次修订。而且这些公告中的受影响范围是针对 Go 模块版本编写的——低于 1.5.27 和低于 1.6.3——而不是 JFrog 公告使用的 transports 发布标签,因此运维人员在将一份文档与另一份文档对照时,必须先协调两套编号方案,才能判断某个构建是否受影响。

Rendered two-column card with the kicker 'BIFROST · CVE-2026-90898' and the title 'What the sources establish — and what they do not', subtitled 'Sources: JFrog JFSA-2026-001686326 (14 September 2026), the CVE record assigned by JFrog, NVD, FIRST EPSS, the CISA KEV catalogue, and the project's pull request 6757 and release tags.' The left column, headed 'ESTABLISHED' in blue, lists eight items: score 9.8 with the vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H supplied by the CNA; CWE-306 missing authentication with CWE-284 access control; unauthenticated POST /api/mcp/client starting a program as the gateway user; affected below transports 2.1.0 when management auth is disabled, the default; fixed in transports 2.1.0, PR 6757 merged 2 September, released 8 September 2026; CISA SSVC of 14 September 2026 with exploitation none, automatable yes, impact total; EPSS 2.3 percent at the 83rd percentile on 27 October 2026; and not in the CISA KEV catalogue dated 27 October 2026. The right column, headed 'NOT ESTABLISHED, OR CONTESTED' in amber, lists eight items: no exploitation reported, and the archive records real harm as false; no count of exposed or affected deployments in any cited source; severity contested, the vendor's CTO telling The Hacker News it is low; no published revision to the score as of 28 October 2026; NVD still Awaiting Analysis, so the 9.8 is the assigner's and not NVD's; affected ranges stated in two numbering schemes across the advisories; no detection or triage guidance in either advisory; and no evidence tying the flaw to any intrusion. A footer reads 'Card rendered by OrcaRouter'. The OrcaRouter logo is composited in the bottom-right corner.

发生了什么变化,以及操作人员被告知要做什么

时间线从披露之日往回倒推,这是记录中最不直观的部分。拉取请求 #6757 于 2026 年 9 月 2 日合并。transports/v2.1.0 是公告所指首个包含修复的版本,于 9 月 8 日发布——比 CVE-2026-90898 于 9 月 14 日发布早六天。该项目的插件修复也同样早于其自身公告:transports/v2.0.0 于 8 月 26 日发布,比 9 月 6 日的 CVE 早十一天。那些跟踪版本发布而非信息流的运维人员,在收到警告之前就已拿到了补丁。

升级带来的好处有限且具体。在 2.1.0 及更高版本中,未经身份验证的 stdio 注册会返回 403,并且该命令不会启动;经过身份验证的管理员仍保留此能力,config.json 预配也仍然有效。对于无法升级的用户,公告给出的临时措施是将 governance.auth_config.is_enabled 设置为 true,使用强管理员凭据,并让管理监听器远离不受信任的网络。对于在禁用身份验证的情况下曾暴露运行的实例,JFrog 的指示不是去调查并抱有侥幸心理:而是将其视为已遭入侵,并轮换虚拟密钥和提供方凭据。

版本号的推算是最容易被误读的部分。v2.0.0 并未修复此缺陷。1.6.x 系列直至 1.6.11 也不包含该修复;该项目最新的 1.6 系列标签是 transports/v1.6.11,发布于 2026 年 8 月 14 日,而截至 2026 年 10 月 28 日,仓库中尚无 1.7 系列——因此该系列内没有已修复的发布版本,使用 1.6.x 的人员必须升级到 2.1.0 或更高版本,而不能等待向后移植。当前发布系列早已远超这一点:transports/v2.3.2 发布于 2026 年 10 月 20 日。

Rendered release-timeline card with the kicker 'BIFROST · RELEASE TIMELINE', the title 'The fix shipped six days before the advisory' and the subtitle 'Dates from the project's release tags and pull request metadata, the JFrog advisories and The Hacker News. Every date below is a single day.' A horizontal timeline carries seven dated markers: 26 Aug 2026, transports 2.0.0 published; 2 Sep 2026, PR 6757 merged; 6 Sep 2026, CVE-2026-86242 published, 8.1; 8 Sep 2026, transports 2.1.0, the fix; 14 Sep 2026, CVE-2026-90898 published, 9.8; 22 Sep 2026, vendor statement reported; 23 Sep 2026, GitHub advisories published. Below it, three bars show release lines: a hatched amber bar labelled '1.6.x line' reading 'affected — no patched release in the series; newest tag 1.6.11, 14 August 2026'; a bar labelled '2.0.0' split between a pale blue segment reading 'plugin flaw fixed' and a red segment reading 'MCP flaw still open'; and a solid blue bar labelled '2.1.0 and later' reading 'MCP fix — unauthenticated stdio registration returns 403'. A foot band headed 'THE PART THAT IS EASY TO GET WRONG' notes that 2.0.0 was the patched release on 6 September and did not close the MCP path, that for the two days before 2.1.0 an operator who patched on the day of the warning was still exposed, and that the 1.6.x series has no fixed release at all. A footer reads 'Card rendered by OrcaRouter'. The OrcaRouter logo is composited in the bottom-right corner.

发布后发生了两件事,防御方可加以利用。该项目的 GitHub 安全公告——针对 MCP 漏洞的 GHSA-86gf-xh3g-rvxq(严重级别)和针对插件漏洞的 GHSA-2qp8-4xgm-fw6g(高危级别)——于 2026 年 9 月 23 日发布,为依赖项和公告源提供了第二个可匹配的标识符。2026 年 10 月 13 日,针对 CVE-2026-90898 的检测模板被合并到公开的 nuclei-templates 仓库,这意味着针对未认证注册尝试的检查现在可以由扫描流水线运行,而不必由每个团队自行编写。

Abstract illustration on a dark navy field: a wide translucent slab representing a credential store, filled with evenly spaced glowing key-shaped tokens, stands behind a low wall. A narrow gateway aperture in the wall holds a fresh, brighter set of tokens, a blank card-shaped slip lies pushed aside on the ground in front of it, and a thin amber arc sweeps from the aperture around to the store. A second gateway aperture in the background remains closed and unlit. No text, no people, no organisation logos.

仍未确定的是严重性评级,而它最终能否得到解决,取决于仍在讨论此事的两个组织。据报道,Maxim 的立场是,9.8 分高估了一个只有在监听器对外暴露且默认设置未启用时才会产生影响的漏洞——这一说法原则上可验证,但尚未经过公开验证,因为没有人公布有多少部署同时满足这两个条件。JFrog 的立场是它作为 CNA 评定的分数,该分数仍保留在 CVE 记录和 NVD 中。在两者之一发布修订之前,无论哪种情况,实际解读都是一样的:该漏洞真实存在,并已在发布的容器镜像上进行了端到端验证;修复在预警发布之前已发布;1.6 系列根本没有修复;任何在可访问监听器上以禁用身份验证方式运行的实例,都应被视为凭据事件,而不是一个待排期的补丁。