返回所有文章
发布于 · 作者 Renaud Deraison

网页改写了代理的配置文件

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 启动了新条目 里的命令,攻击者的代码便以开发者的权限在主机上执行:足以读取凭证、复制源代码、 植入持久化,或横向移动到开发者机器所能触及的一切。

开发者的机器 — 一个信任区文档页面在人眼看来很正常…1px 白字:“覆盖 mcp.json”Kiro 代理把页面当文本读照做,调用 fsWritemcp.json不是清单 — 是启动器。重载即执行其命令代码执行以开发者身份:凭证、源代码、云端、横向在读取页面与执行代码之间,没有批准提示。CVE-2026-10591 — 2026年2月上报,v0.9.2 / v0.10.16 上存在,v0.11 系列修复。
CVE-2026-10591,由左至右,全都在开发者的机器上。一个文档页面以一像素白字夹带指令,在浏览器中不可见,对代理却是纯文本。被要求读取页面时,Kiro 依循被夹带的指令,用自己的 fsWrite 工具覆盖 ~/.kiro/settings/mcp.json。那个文件是个启动器:重新加载时,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 防火墙。

正常设置 — 一台机器隐藏页面 → Kiro 改写 mcp.json →代码以你的身份在你的 Mac 上执行真实密钥与令牌被窃源代码与云端可触及植入的 MCP 服务器留存跨越重启提示是唯一的线,而它被越过了。Bromure Agentic Coding — 用完即弃 VM同一连锁触发 — 在 VM 内,以用完即弃的 ubuntu 用户抓到诱饵brm_… ,非真实密钥外发被把关在主机代理处记录关闭会话 → 箱子重置植入的服务器与持久化消失线是 hypervisor,不是提示。
同一场攻击,两台机器。在正常设置下(左),被注入的代码在开发者的 Mac 上执行,并触及紧邻其旁的真实凭证、源代码与云端会话。在 Bromure Agentic Coding 下(右),完全相同的连锁在一个用完即弃的 VM 里执行:代码以一个用完即弃的 ubuntu 用户身份执行,它抓到的凭证是诱饵,它的外发请求在主机代理处被把关并记录,而关闭会话会重置箱子,抹去被植入的 MCP 服务器与任何持久化。hypervisor 就是那条模型无法靠言语越过的线。

接着是外发的那一半。窃取一个诱饵,唯有你能把它送到某处才划算;而横向移动意味着 抵达第二台主机。两者都是网络动作,在 Bromure 中两者都穿过主机代理,在那里一个请求 真正的目的地会在外发途中被把关,而一个动作的破坏性形态 — 对配置文件所代管的云端与 git API 发出的 delete、drop 或 terminate — 会遇上一道能拒绝它的护栏,无论代理被说动 去做什么。被启动的代码所尝试的一切,都会在会话轨迹里留下一行记录。

而在这一切之前还坐着一层,理由正好贴合这场攻击。Bromure 会为代理所读的不受信任 内容 — 一个抓取的页面或一则工具响应 — 在模型据以行动之前,用一个设备端的 注入检测器评分。一像素文本之所以有 效,是因为人读的是渲染后的页面。分类器不然;它读的是模型所读的同一道原始流,在那里 color:#fff;font-size:1px 什么也藏不住。那个让段落对眼睛隐形的把戏,对读取字节的 评分器毫无差别。它拦下其中大部分,而够新奇的伪装仍可能溜过单一检测器,因此它坐在 用完即弃的箱子之前,而非取代它。

如今网络就是那不受信任的输入

多年来,给编程代理的建议是:小心你信任哪些仓库。Kiro 把这课往前推:危险的输入是一 个文档页面,代理一天要读上百次的那种,而武器是一个浏览器自 1990 年代就一直尊重的 CSS 属性。随着开发流程越来越多经由阅读开放网络的代理,每个页面都是不受信任的输入, 而读得再仔细也修不好这件事。

AWS 加上的提示是正确的修补,也应该推出。但一个仰赖某人在每个页面上、永远地抓到那 唯一要紧的写入的控制,是一个长期成绩很差的控制。Bromure Agentic Coding 不要求代理 对网络小心。它假定页面得逞、配置被改写、代码执行,并确保当这一切发生时,是发生在一 个没有东西可拿、也没有回家路的箱子里。这就是一个你能用言语绕过的提示,与一条画在低 一层、言语在那里失效的线,两者之间的差别。安装它,给你的代理一 台不是你输得起的机器。