那道网关接受任何一个令牌
9 月 2 日,CISA 把七个已遭利用的漏洞加入 KEV 目录。其中三个是 AI 基础设施,这是 AI 占了将近一半的第一批。读读 LiteLLM 那一条:它的 MCP 端点会放行一个带着任何 Bearer 令牌的未认证请求,因为密钥校验失败后落进了一个空的认证对象,而调用方接着就能列出并调用网关所接上的每一个工具。Bromure Agentic Coding 把同样的权限放在一个 hypervisor 与一条 vsock 之后:没有在监听的端口、没有可伪造的标头,也没有回退分支。
你建起这道网关,是为了不让任何一台笔记本握着全部的密钥。它成功了,于是它握着 全部的密钥。后来它的前门接受了一个由某人随口编出来的 Bearer 令牌。
9 月 2 日,CISA 新增了七个漏洞 到 Known Exploited Vulnerabilities 目录。两个 SonicWall SMA1000 的问题、一个 Sangoma Switchvox 的 SQL 注入、一个 JFrog Artifactory 的认证绕过、一个 Kestra 的操作系统命令注入、一个 Starlette 的 HTTP 走私缺陷,以及 BerriAI 的 LiteLLM 的一个不当认证缺陷。
这七个里有三个是 AI 与 ML 基础设施。Forkast 称之为 AI 组件占了新增项将近一半的第一批 KEV, 那种先挣得一则标题、然后就被归档的里程碑。但看看它们是哪一类 AI 基础设施, 这一批就值得多过归档。三个都坐在中间:它们正是你部署下去,好让你的智能体与 它们所触碰的资源不再直接对话的组件。就从 LiteLLM 那一条开始。
那条回退分支
LiteLLM 是一道 AI 网关:一个代理,站在你的智能体与模型供应商之间,替所有人 保管供应商密钥,执行预算与速率限制,写下日志,如今还向 Model Context Protocol 服务器展开,好让一个团队的智能体共用一个 MCP 端点,而不是每位开发者各自接上 自己的。
CVE-2026-59822 于 7 月 8 日公开, 在 GitHub 的公告中带着 8.8 的 CVSS, 就住在那个 MCP 端点上。公告里的一句话承载了整个故事:
回退路径可能以一个空的
UserAPIKeyAuth()对象,取代失败的 LiteLLM 密钥 校验。
MCP Streamable HTTP 端点支持 OAuth2 直通,好让一个原本要给上游 MCP 服务器的 令牌能穿过网关,而不是拿去和 LiteLLM 自己的密钥库核对。这是个合理的功能, 而它需要一个分支:先试 LiteLLM 的密钥,如果送来的不是密钥,就走直通那条路。
你靠"失败"抵达那条分支。发出一个 Authorization 标头,里面放任何字符串都行,
密钥校验因为那字符串不是密钥而拒绝它,于是处理程序建出一个空的
UserAPIKeyAuth(),带着它继续往下走。你的请求此刻握着一个不属于任何人的、
已认证的 MCP 会话。从那里,你可以把网关配置过的每一个 MCP 工具都列出来并
调用:内部应用程序、数据库、云控制台、开发系统,团队接上去的任何东西。
这个缺陷影响 1.84.0 之前的所有版本。CISA 给联邦机构的修复期限是 9 月 16 日,
而 LiteLLM 给今天无法升级者的建议是:在前面的反向代理上挡掉 /mcp/。
另外三个,坏在同一个函数
把这一批剩下的读完,你会得到比"AI 对非 AI"那则标题更有用的东西。
Starlette,CVE-2026-48710,绰号 BadHost。Starlette 是 FastAPI 底下的 ASGI
工具包,Python 的 AI 服务有很大一部分建在它上面,LiteLLM 也在其中。一个特制的
Host 标头把一段路径注入到请求的主机部分,这改变了 URL 被重建的方式,也就
意味着以路径为准的认证中间件评估的是一条路由,而应用程序端出的是另一条。
CISA 的条目写明了结果:当认证取决于重建后 URL 的路径时,会发生认证绕过。它的
CVSS 是 6.5,是这一批里最低的分数,也是最说不出后果的那个分数。LiteLLM 在
1.84.0 也交出了
针对同一形状的自家配套修正,
描述为"一个特制的 Host 标头可能让代理的认证关卡去评估一条与实际端出者不同
的路由",并告诉那些代理曾对外暴露的运维者:轮换密钥,审计管理日志。
JFrog Artifactory,CVE-2026-82329,CVSS 9.8。默认配置下的不当认证:一把
"幽灵" join key,让未认证的攻击者能伪造管理员令牌。watchTowr 在 9 月 1 日,
也就是披露后四天,记录到真实环境中的利用:攻击者铸造管理员凭据并枚举用户。
这是制品仓库,是替整个组织回应 npm install 与 pip install 的那台主机。
Kestra,CVE-2026-49869。未认证的远程攻击者可触及的操作系统命令注入, 他不需要任何凭据,就能创建并执行任意工作流。编排器做着编排器该做的事—— 只是替一个从未登录过的人做。
四个产品,四套不同的代码库,而每一套里坏掉的是同一个函数:决定这个请求 够不够格待在这里的那一个。一个空的认证对象。一条重建出来的路径。一把默认的 join key。至于 Kestra,是那条负责执行的路由上根本没有检查。
攻击者接下来做的事很无聊,而无聊正是规模化作业的迹象。The Hacker News 整理了观察到的行为: 反向 shell、XMRig 挖矿程序、凭据枚举,以及窃取 API 密钥与 LLM 供应商凭据。 Microsoft 总结道:
观察到的目标是一致的。在这些案例中,遥测数据显示了凭据收集、持久访问机制与 资源变现,尽管执行路径因产品而异。
网关是对的主意,而这是它的账单
AI 网关是这两年比较好的主意之一,而多数团队走到这一步都有扎实的理由。
在网关之前,每位开发者的编码智能体都把一把供应商密钥放在环境变量里,每位 开发者用自己的令牌接上自己的 MCP 服务器,而没有人答得出这一切花了多少、 碰过什么。在中间放一道网关,一次就把这些都解决了。一个地方保管供应商密钥与 MCP 配置,并写下日志。轮换一把密钥变成单一动作,切断一位离职员工也是。 这个行业会收敛到这里,是有道理的。
账单是:你盖了一个网络服务,它存在的全部意义就是替所有人保管权限,而它用 一个函数来决定你是谁。函数有分支,其中一条分支负责处理"你先试的那件事没成" 这种情况。
这个形状不是 LiteLLM 发明的。每一道网关都有前门,每一扇前门都有一个认证函数, 而一个支持两种凭据方案的认证函数,会有一条在第一种失败时走的路。门后那片 触及范围是刻意的:把它集中起来,正是这项产品本身。所以当一道网关出事时, 它保管的一切早就都在同一个房间里了。
从这种事故通常被导出的结论是"回去用每位开发者各自的密钥",而那在任何一项 度量上都更糟。继续集中。真正值得争论的问题是那个集中起来的东西坐在哪里, 以及它是否非得回应陌生人的请求才能完成它的工作。
Bromure 把同一份工作放在哪里
Bromure Agentic Coding 让每一个编码智能体跑在你自己 Mac 上、由硬件虚拟化的 Linux VM 里,而每一项安全控制都坐在那道边界的宿主侧。这些控制和一道网关提供的 是同一份清单:保管凭据、居中处理 MCP 服务器、分类智能体对你基础设施做的事、 留下记录。网络上没有任何东西能碰到执行这些控制的组件。
没有前门。 客户机的 HTTPS 从不经由网络离开。它走一条 virtio 套接字、vsock
端口 8443,隧道到宿主端的代理,而手册对拓扑讲得很直白:这台 VM 没有其他通往
网络的路径。那个代理没有任何在监听的端口,能让你的局域网、你的公司网络或
互联网寻址得到。它从不问是谁在调用,因为那条套接字的另一端只有一样东西,而
那是什么由 hypervisor 决定。没有 Authorization 标头、没有密钥库、没有方案
协商,因此也没有第一种方案失败时要走的分支。
MCP 的 bearer 令牌,在抵达智能体之前就已经是假的。 对于工作区里配置的
HTTP 传输 MCP 服务器,真正的 bearer 令牌始终加密留在 Mac 上。智能体的配置
拿到的是一个 brm-mcp_… 占位值。设置面板把那个字段标注为绝不发送进 VM——
由代理替换,而宿主端的代理会在链路上换进真值,范围限定为该服务器主机的完全
匹配或子域匹配,别无其他。代理还会对该服务器的 OAuth 与 OIDC 发现路径返回
404,好让 Claude Code 把那台服务器当成已预先认证,而不是去尝试一段 VM 永远
完成不了的浏览器流程。LiteLLM 的回退,正是站在同一片直通表面上。在这里,
工作区根本没有可以失手的凭据。
每一次操作,都有自己的一次判断。 一道网关在门口把问题了结:过了门,
后面的一切都是你的。Bromure 的 Guardrails 在代理内部分类智能体的调用,横跨
Kubernetes、AWS、git 托管站、容器镜像库与数据库,并套用逐服务的写入策略。
新工作区默认是写入前先问,于是读取照流,而每一次变更都会停在宿主侧的一个
对话框上,上面显示字面上的那个操作:确切的 SQL,或 方法 /路径。只读
挡掉一切变更。使用前先问则管住凭据本身,授权以分钟计。就算是一个伪造的
会话,也依然没办法靠 kubectl delete 一路推过去,因为第二次判断发生在
你的 Mac 上,和第一次的结果毫无关系。
默认拒绝,在两个方向上都回答了可达性。 工作区的出站防火墙是一张有序的 规则表,并为未匹配的流量设定默认值。把它设成拒绝,这台 VM 就只能到达你 列出的主机,在任何协议上都是如此。客户机之外的两个组件执行这件事:虚拟交换机 以目的 IP 与从 DNS 侧录到的主机名匹配每一条流,而代理再以 TLS 服务器名匹配 一次。编辑不必重启就会送到进行中的会话。反方向上,NAT 模式让这些 VM 待在 你的物理局域网之外,除非你刻意发布某个服务,否则外面没有任何东西能对它们开启 连接。那些把暴露网关一网打尽的扫描器,从一台 Mac 得不到任何回应。
一道被拿下的网关送回来的任何东西,都是不可信输入。 这一点比那个 CVE 活得
更久。一旦网关归了别人,模型输出、工具结果与错误字符串就全都来自攻击者,而且
走在整个栈里权限最高的那条线上:智能体天生就会据以行动的那条。Bromure 的
源代码检测器会用一个本地的 PromptGuard 模型,在设备上,于模型据以行动之前,
为智能体外发 AI 流量中的 tool_result 片段打分,并可以记录、询问或阻断;
一次阻断会返回 HTTP 451,模型永远看不到那段内容。
外泄那一段会朝关闭的方向失败。 工作区里的每一份凭据,都是一个只有单一 合法目的地的确定性假货。代理会扫描每一个外发请求,找出正要前往铸造范围以外 之处的假货;找到时,它一个字节也不转发就拒绝请求,暂停这台 VM 并发出警报, 以一行红色的凭据中介记录在 Security Timeline 上。因为当初能被碰到的只有 假货,真凭据不需要轮换。
如果你今天在运营一道网关
把 LiteLLM 升级到 1.84.0 或更新;若做不到,就在前面的反向代理上挡掉
/mcp/。接着照 LiteLLM 自己针对 Host 标头修正给出的建议,把一个曾经暴露的
代理当成一个暴露的密钥库来处理:轮换它保管过的供应商密钥,审计管理日志。
联邦机构在 CVE-2026-59822 上的期限是 9 月 16 日,那是个可以借来用的合理
日期。
那条让问题变小的规则
在工作区的 Guardrails 面板里,把未匹配流量设成拒绝,然后列出
这份工作真正需要的东西:allow web api.github.com、
allow web registry.npmjs.org、default deny。一个不被允许碰到内部网关的
工作区,也就不能被拿来穿过任何一道网关;而且保存后,策略不必重启就会推送到
进行中的会话。
保管机密,不要检查它
在这样的一周之后,Bromure 自己架构笔记里的一行值得重读:
绕过这道边界,攻击者什么也拿不到,因为这道边界不是机密被检查的地方—— 它是机密存在的唯一地方。
网关是凭据被检查的地方:一个请求抵达,一个函数检视它,而那个函数的裁决是 调用方与密钥之间唯一的阻挡。检查有边缘情况,也有回退路径。检查会挣得一个 CVE、一则 KEV 条目与一个联邦期限,然后两个月后在同一个函数的另一条分支上, 再挣得一个。
链路边界则是凭据所在的地方。没有东西抵达等着被检视,因此也没有裁决可以出错。
真正的令牌加密躺在一台 Mac 上,工作区握着一个在任何地方都一文不值的 brm-
占位值,而替换发生在一条只有 hypervisor 写得进去的套接字上。
我们在六周内已经把这件事的变奏写过三次:一个 信任了智能体可以自己写入的主机名的出站代理、 一个 读 bash 的方式和 bash 不一样的命令守卫, 以及 三个编码智能体,它们的绕过最后都落在某个进程里的一份真凭据上。 每一次,失守的那个组件都在诚实地做着"评估某件事"的工作,而这正是不变的地方。 评估是比不存在更弱的原语,而我们却一直把不存在能免费完成的工作,交给评估去做。
把你那些智能体的权限集中起来,是对的决定。请把那个集中起来的东西,放在没有人 能对它发出请求的地方。安装 Bromure Agentic Coding, 给每一个智能体一道没有前门的边界。