代理信任了标点符号
Agent Data Injection 是首尔大学、UIUC 与 Largosoft 于 2026 年 7 月发表的概念验证,它不把指令藏在提示里。它伪造代理用来区分可信字段与不可信文本的标点——一个弯引号、一个转义引号,甚至一个走失的美元符号——好让攻击者的 GitHub 评论被读成维护者自己的修复,一份伪造的 CI 记录被读成一次干净的构建。它在 GPT-5.2、Claude 与 Gemini 上,最多有一半的时候绕过了专门打造的提示注入防御。Bromure Agentic Coding 在文本成为计划之前先把伪造的分隔符规范化,锁住那些伸出盒外的执行这个、合并这个动作,并把整件事跑在一台装着诱饵凭据的一次性 Linux VM 上。
你的编程代理靠着读取周围的标点,来决定该服从哪段文本——那些说着这一段是 维护者、那一段是陌生人评论的引号与花括号。一种新的攻击伪造那个标点。它不写 一条更巧妙的指令。它写一个弯引号,于是陌生人的评论便开始戴上维护者的名字。
2026 年 7 月 6 日,首尔大学、伊利诺伊大学厄巴纳-香槟分校与 Largosoft 的研究者 ——由 Woohyuk Choi 与 Byoungyoung Lee 教授领衔——发表了一篇标题直白的论文: Agent Data Injection Attacks are Realistic Threats to AI Agents。 它描述了一类攻击,Agent Data Injection(ADI),它坐在提示注入的旁边而非 其中,并在古典提示注入近乎零分之处, 最多有一半的时候绕过了专门打造的注入防御。 OpenAI、Google 与 Anthropic 都证实它有效。发表时尚未报告任何修复。
它之所以对任何跑着编程代理的人都要紧,是因为它攻击一件代理忍不住要信任的 东西:它取得的数据,与那份数据到来时所带的结构,两者之间的边界。
分隔符就是安全边界
代理的上下文是一堆来自众多来源的文本——你的指令、一个文件、一个网页、某人在 议题下留的一则评论。为了明智地行动,模型必须记住哪一块是哪一块:这是维护者 的名字,那是某个陌生人写的评论正文。它以文本所允许的唯一方式做这件事——用 标点。引号与花括号、标签、方括号、换行。分隔符标出一个可信字段在何处结束, 不可信内容又在何处开始。
严格的解析器照字面对待这些分隔符:引号就是引号,评论中间的一个字符就只是一个 字符。语言模型不然。照论文的说法,它靠猜测读取标点——它从那些字符看起来像 什么意思,推想出结构。这正是全部的破口。一个掌控低信任字段——一则产品评价、 一则 GitHub 议题评论、文件里的一行——的攻击者,把像标点的字符撒进去,模型便 读出一个从不存在的结构。
令人不安的细节,是它需要的手艺有多么少。研究者把这技法称为概率式分隔符注入, 并发现那假的标点甚至不必是对的。一个转义引号、一个弯引号,甚至一个走失的美元 符号,都能冒充一道真正的字段边界并骗过模型。严格的解析器本会把它们每一个都读成 寻常文本。
它对编程代理做了什么
ADI 的网页代理版本很容易想象:伪造页面元素上的标识符,一个替你购物的代理就会 在它本想点阅读更多之处点下立即购买。瞄准开发者的版本更糟,因为它伪造的可信 字段,是谁说了那段代码是安全的。
在一次演示中,攻击者在一则 GitHub 议题下评论,并伪造作者归属,好让代理把它读成 来自项目的维护者。当开发者稍后请代理套用维护者的修复时, Claude Code、OpenAI 的 Codex 与 Google 的 Gemini CLI 正是照做——它们执行攻击者的命令,因为就模型所能判断,是维护者要求的。在另一次 演示中,一个恶意的拉取请求伪造了它自己已完成 CI 检查的记录。代理在上下文里看见 一次干净的构建,凭那份捏造的证据判断代码安全,于是合并了真正的恶意软件。
在团队测试的六个模型——GPT-5.2、GPT-5-mini、Claude Opus 4.5 与 Sonnet 4.5、 Gemini 3 Pro 与 Flash——之间,这些数字不是舍入误差。结构化数据的成功率为 31 至 43%;网页数据则从 33% 一路到 100%。而面对专为拦截提示注入而建的防御, ADI 仍然最多有一半的时候穿过去,在那些相同防御冷冷挡下古典注入之处。两种 缓解措施在实验室里奏效,两者都付出了代价:以随机、猜不到的 ID 标记页面元素 (如 ChatGPT 的 Atlas 浏览器所为)把成功率从约 49% 砍到 29%,而严格的数据来源 追踪把攻击逼到零——同时把代理完成正常任务的能力压到约三分之一。
为何寻常的过滤器会漏掉它
一个提示注入过滤器受过训练,去注意藏在数据里的指令——忽略你先前的指示、执行 这个命令,那种乔装成内容的命令的可辨形状。ADI 不需要那个形状。恶意的文本读起来 可以像一则寻常的维护者备注。载着攻击的是它周围的标点,而一个为可疑措辞而读的 过滤器,会从一个弯引号旁一路航过。这正是为何论文自己那道奏效的防御,不是更聪明 的分类器,而是更严格的解析器——一种拒绝去猜字段在何处结束的来源追溯。
这正是代理式安全的其余部分不断重新学到的教训。一份命令拒绝清单 败给了改写命令的 shell。 一个受信任的 MCP 工具 交回攻击者写的数据。 一个你信任的工作区 启动了你不想要的服务器。 ADI 是那个版本,被下毒的既不是指令也不是数据,而是那道框——那个告诉代理该 相信哪段文本的分隔符。你无法靠比对模式脱出一个弯引号。
Bromure 在哪里画线
Bromure Agentic Coding 不试着把模型变成一个更会猜字段在何处结束的猜测者。它做 两件模型做不到的事,然后确保当两者都错时,损害落在某个可丢弃之处。
首先,伪造的分隔符在文本成为计划之前就被规范化。 Bromure 的设备端提示注入
检测,不只是一个读取意图的本地模型;它与一个确定性扫描器配对——就是那个逮住
隐形 Unicode 与同形字花招的扫描器。弯引号折回直引号,易混淆与零宽字符被剥除,
而分隔符不合规范结构的字段会被标记。这正是研究者发现能击败 ADI 的那股严格解析
本能,作为一层施加在代理取得的不可信文本上——与恶意的 CLAUDE.md 或被下毒的
评论同一类的输入——而这一切都留在你的 Mac 上。
其次,ADI 真正想要的那两个动作,仍然停在一道边界前。 看看这攻击试图触发 什么:执行维护者的修复,以及合并那个拉取请求。 两者都是伸出代理沙箱之外的 动作——一道 shell 命令、一次推送到远端。Bromure 所跑的每个代理——Claude Code、 Codex、Grok Build——都跑在一台一次性 Linux VM 之中,而离开那盒子的步骤,正是 Bromure 呈上来请你确认的。一次伪造的归属得不到自动执行一道命令,一份伪造的 CI 记录得不到自动合并一条分支,因为维护者这么说正是确认步骤存在来复核的那个判断。
第三,若一道命令真的跑了,它跑在一个你丢掉的盒子里。 假设某个分隔符新到能 溜过规范化器,又有说服力到能通过审查。命令在 VM 之中执行。把配置文件重置回基底, 它所丢下的一切——一个脚本、一把 SSH 密钥、一个计划任务——都不见了。它所做的 没有一样熬得过窗口关上。
第四,没有真正的凭据可供它取走。 一个在环境与磁盘中搜刮令牌的修复,找到的
是 Bromure 的诱饵——合成的 AWS 密钥、一份一次性的 ~/.kube/config、占位的 git
与注册表令牌(brm_…)。真正的机密只在主机上、在代理程序里、在通往真正 API 的
出口途中才被换上。命令送出盒外的一切,是一袋什么都认证不了的字符串,而送出它的
那条连接,会在安全日志里现身为一笔你看得见的外发流量。
这替什么画下界线
规范化与确认是围堵,不是替一个靠猜测读结构的模型治病。值得精确说清 Bromure 改了什么、又没改什么。
评论仍旧被种下
Bromure 不阻止攻击者留下一则伪造的 GitHub 评论,也不阻止他伪造一份 CI 记录,更不修正底下那个事实——语言模型会推想字段在何处结束。那些是模型与 平台该解的。Bromure 改的是代理读了伪造文本之后所发生的事:它被规范化,而它 试图触发的动作被查核。
规范化是一张网,不是一堵墙
折回弯引号、剥除易混淆字符、标记不相符的分隔符,逮住研究者演示的那些 ADI 花招与更多,但一个新奇的分隔符可以被措辞成溜过单一扫描器。把它当成一层;那个 装着诱饵密钥、外发有记录的一次性盒子,才是扫描器漏掉时撑住的东西。
确认守的是边界,不是每一次编辑
确认步骤在离开盒子的动作上——执行一道命令、推送、合并——挣得它的位置。一条只 在 VM 内编辑一个文件的伪造指令,由隔离与诱饵逮住,而非由提示。把边界动作 上锁;那正是一句伪造的维护者这么说值得再看一眼之处。
替换涵盖你所设定的机密
诱饵替换保护的是你放进配置文件的凭据:模型密钥、git 与云端令牌、注册表与集群 令牌、SSH 密钥。一个脚本在执行途中写进磁盘的令牌,或你在盒中亲手开的一个 会话,就只是数据。把机密留在中介里,别留在工作区。
研究者的重点,不是六个模型共用一个缺陷。重点是,代理区分可信字段与不可信内容 的方式——它靠猜测读的标点——在代理与外界相遇的每个地方都一样,而它这一季不会被 修好。今天,伪造的分隔符住在一则 GitHub 评论里。明天,它是一个 Jira 字段、一行 commit trailer、一个取来页面上的标头。你的代理终将读到一道由攻击者画下的边界, 而最多有一半的时候它会相信。问题不在标点会不会有一天骗倒它。问题在于它被骗倒时 什么会跑起来:你的机器、你真正的令牌,以及一道把自己推上 main 的命令——还是一个 一次性的 Linux 盒子,先把那引号规范化,把合并扣下来看一眼,里头除了诱饵别无 他物。Bromure 让它是后者。