网页改写了代理的配置文件
2026年7月21日,Intezer 与 Kodem Security 披露了 CVE-2026-10591:一个看似普通的文档页面以一像素白字夹带指令,当开发者请 AWS 的 Kiro 代理读取它时,Kiro 用自己的文件写入工具,在毫无批准的情况下覆盖了启动其 MCP 服务器的配置文件,接着重新加载该文件并在主机上以开发者的权限执行了攻击者的代码。AWS 加上了批准提示。真正留下的,是代理、它所读的网页与开发者的机器同属一个信任区。Bromure Agentic Coding 在它们之间放上一层 hypervisor。
开发者请 Kiro 读一个文档页面。页面里有一句以一像素白字书写的话,是写给模型看 的,不是给眼睛看的。顺着它,Kiro 改写了决定自己启动哪些程序的文件,然后启动了 一个。这一切都不需要点击。
Kiro 是 AWS 的代理式 IDE:一个代你阅读开放网络、抓取文档并替你接上工具的编程
代理。和 2026 年多数代理一样,它说 Model Context Protocol,即 MCP:让编程代理调用
外部工具并读取其结果的插头。Kiro 把它的 MCP 服务器清单,以及启动每一个所用的确切
命令,存在一个位于 ~/.kiro/settings/mcp.json 的朴素文件里。当这个文件改变时,
Kiro 会重新加载它,并启动它此刻所描述的一切。
最后这句话就是整个漏洞。这个文件是个启动器,而代理能写入它。
2026年7月21日, Intezer 在与 Kodem Security 的研究中,展示了随之而来的连锁, The Hacker News 当天便报道了它。AWS 指派了 CVE-2026-10591, 评为 10 分中的 8.8。同一问题较早的片段,早已由 Johann Rehberger 与 Cymulate 指出。 Intezer 所加上的,是投递。
一个你读的页面,而非你打开的文件
指令并非来自某个仓库,或开发者选择信任的配置。它们来自一个网页。Intezer 把它们以
一像素白字、color:#fff;font-size:1px,种在一个其余部分毫不起眼的 API 文档页面
上。在浏览器里,这段落什么也不呈现:一条人类滚动时直接略过的空白细片。对于吞入
页面文字而非其图像的代理而言,它是一段清楚的指令。
这些指令要 Kiro 使用自己的文件写入工具 fsWrite,以攻击者提供的条目覆盖
~/.kiro/settings/mcp.json。Kiro 没问就照做了。它默认的 Autopilot 模式自行写入该
文件,没有对话框,也没有“允许这次写入吗?”的提示。重新加载触发,Kiro 启动了新条目
里的命令,攻击者的代码便以开发者的权限在主机上执行:足以读取凭证、复制源代码、
植入持久化,或横向移动到开发者机器所能触及的一切。
AWS 加了提示。机器仍是奖品。
这修补是明智的。AWS 如今把 mcp.json、.vscode/tasks.json、.git 目录,以及其他
对执行敏感的文件标记为受保护路径:写入其中任一个都需要明确批准,Autopilot 与
Supervised 模式皆然。原先缺席的批准步骤,现在有了。若你使用 Kiro,请更新它。
这修补没有改变的,是房间的形状。AWS 在结语中也如此说:唯有当一个人被展示了那个 关键的步骤,且在模型被彻底说服而越线之后平台仍守住那条线,人在回路中才作为一种 控制发挥作用。这是两项要求。提示满足了第一项:它把写入摊到眼前。它无法满足第二 项,因为当代码执行时,它在开发者自己的机器上、以开发者自己的触及范围执行。你在 疲惫的午后一路点过去的批准,或是下一个聪明页面学会措辞得让它看来例行的批准,都把 你带到同一个地方:攻击者的代码,在你的密钥、你的仓库与你的云端会话所在之处执行。
这里反复出现的形状 — 代理读过的页面、它能写的配置、它能触发的启动 — 并非 Kiro 独有。它就是一个阅读开放网络、并在满是机密的机器上编辑文件的代理的样子。持久的 问题是:代理在哪里执行,以及当提示失效时它周围有什么。
Bromure 执行相同步骤之处
Bromure Agentic Coding 不试图让代理不信任页面、拒绝写入或拦下点击。它改变整个序列 所执行的那台机器。每个配置文件的代理,都在 Apple Silicon 上一个用完即弃的 Linux VM 里执行,与 macOS 隔着一层 hypervisor。在那里执行 CVE-2026-10591 完全相同的连锁, 每一步仍会触发,而每一步都落在不同的地方。
页面被读取。注入得逞。Kiro 的替身改写 mcp.json,重新加载触发,攻击者的命令“以
开发者的权限”启动。只是在 VM 里,开发者是一个用完即弃的箱子中的 ubuntu 用户,而
那箱子里没有任何值得跑这一趟的东西。代码去寻找那些让攻击划算的凭证 — Anthropic
密钥、AWS 密钥、GitHub 令牌 — 找到的却是诱饵。在 Bromure 中,真正的机密从不进入
VM;主机上的一个凭证中介注入像 brm_… 这样
的占位符、一份合成的 kubeconfig,以及一把用完即弃的 SSH 密钥,只在网络边界、对你已
批准之目的地的请求上,才换入真正的值。源代码窃取只触及你选择挂载的文件夹。“横向
移动进内部系统”则触及每个配置文件各自的 VM 防火墙。
接着是外发的那一半。窃取一个诱饵,唯有你能把它送到某处才划算;而横向移动意味着 抵达第二台主机。两者都是网络动作,在 Bromure 中两者都穿过主机代理,在那里一个请求 真正的目的地会在外发途中被把关,而一个动作的破坏性形态 — 对配置文件所代管的云端与 git API 发出的 delete、drop 或 terminate — 会遇上一道能拒绝它的护栏,无论代理被说动 去做什么。被启动的代码所尝试的一切,都会在会话轨迹里留下一行记录。
而在这一切之前还坐着一层,理由正好贴合这场攻击。Bromure 会为代理所读的不受信任
内容 — 一个抓取的页面或一则工具响应 — 在模型据以行动之前,用一个设备端的
注入检测器评分。一像素文本之所以有
效,是因为人读的是渲染后的页面。分类器不然;它读的是模型所读的同一道原始流,在那里
color:#fff;font-size:1px 什么也藏不住。那个让段落对眼睛隐形的把戏,对读取字节的
评分器毫无差别。它拦下其中大部分,而够新奇的伪装仍可能溜过单一检测器,因此它坐在
用完即弃的箱子之前,而非取代它。
如今网络就是那不受信任的输入
多年来,给编程代理的建议是:小心你信任哪些仓库。Kiro 把这课往前推:危险的输入是一 个文档页面,代理一天要读上百次的那种,而武器是一个浏览器自 1990 年代就一直尊重的 CSS 属性。随着开发流程越来越多经由阅读开放网络的代理,每个页面都是不受信任的输入, 而读得再仔细也修不好这件事。
AWS 加上的提示是正确的修补,也应该推出。但一个仰赖某人在每个页面上、永远地抓到那 唯一要紧的写入的控制,是一个长期成绩很差的控制。Bromure Agentic Coding 不要求代理 对网络小心。它假定页面得逞、配置被改写、代码执行,并确保当这一切发生时,是发生在一 个没有东西可拿、也没有回家路的箱子里。这就是一个你能用言语绕过的提示,与一条画在低 一层、言语在那里失效的线,两者之间的差别。安装它,给你的代理一 台不是你输得起的机器。