AI Agent审批门只校验动词,不校验对象:三大逃逸路径与七层根因

只审批动词不绑定对象的human-in-the-loop门禁,会被间接注入绕过。
文章通过一个红队实验揭示:AI Agent的人类审批门禁普遍只检查“工具是否被允许调用”,却不绑定“批的是哪笔交易”。作者的模拟系统在十个拒绝测试中全部通过,但五个仅改变参数的测试中有三个失败——收款账户被替换、金额从1840美元改成18400美元、以及通过被视为永远安全的send_reply工具外泄通讯录。根源在于控制面与数据面塌缩进同一个上下文窗口,指令与数据失去结构性分隔。作者归纳七个独立根因,并给出修复方案:把审批签名绑定到精确参数并在执行时复检、出口做污点追踪、给审批人看原始参数、标注检索来源、按任务最小权限运行、测试对象而非只测动词。
大多数AI Agent的human-in-the-loop(人类在环)审批机制,都只回答一个问题:这个工具是否被允许调用? 审批人对着approve_payment点一下“通过”,门禁就算满足了。
但这次审批绑定的是动词,不是对象。它没有和“这笔钱付给谁、付多少、对应哪张发票”绑定,于是审批之后Agent读到的内容,仍然能决定钱实际流向哪里。
一位开发者在B站与Dev.to上同步分享了他的红队实验:搭了一个模拟公司,包含helpdesk、财务、代码评审和发布四类Agent,外挂一层策略。策略的拒绝测试10/10全部通过。随后他写了五个新测试,动词不变、只改对象,结果三个失败。
这个问题指的是:间接提示注入配合“动词级审批”形成的逃逸路径,以及为什么一张全绿的记分卡会完全看不到它。
信任边界到底在哪:控制面与数据面塌缩成一个上下文窗口

上图把Agent系统分成两行。上一行是控制面:请求发起人、系统提示词、策略检查、审批人。下一行是数据面:按其“谁可以写入”来标注来源——wiki runbook、发票字段、PR描述、工单历史消息。
设计上两者之间有一条虚线边界。现实中,这两行被塞进同一个context window,虚线就消失了。一个承包商编辑的wiki段落、一张被改过的发票,与系统提示词、与SRE负责人的指令,在模型眼中是同一种token。
投稿者在图注中明确了这个观察:控制面和数据面的塌缩,是后续所有问题的结构性前提。
间接提示注入(Indirect Prompt Injection) 是指攻击者不直接向模型输入恶意指令,而是将指令藏在模型后续会读取的外部内容中——比如网页、文档、工单、邮件或代码注释。当Agent为了完成任务去检索或读取这些内容时,恶意指令便随数据一同进入上下文,被模型当作合法指令执行。它与直接注入的区别在于:攻击者和受害者不在同一条消息里,攻击面是Agent的整个信息摄入管道。这类攻击尤其危险,因为被污染的内容往往来自看似可信的业务系统,且可以在Agent获得审批之后才生效,从而绕过事前门禁。
10/10 的记分卡到底测了什么
十个测试fixture里,有九个是直接注入:攻击者文本和请求出现在同一条消息中。只有一条——被投毒的wiki笔记——是真正的间接注入。
而且每个测试问的都是同一个问题:门禁是否拦住了这个特权动词?
它拦住了。门禁接线是正确的。但这没有告诉你任何关于参数的信息。一个只检查动词的策略层,对“批的是哪笔交易”是盲的。
测试夹具(Test Fixture) 在软件测试中指预先编排好的输入数据与运行环境,用来让被测系统在可控条件下表现出特定行为。本文中的十个fixture就是十段精心构造的Agent输入:其中九个把攻击者文本和用户请求放在同一条消息里,模拟直接注入;另一个把恶意内容藏进wiki笔记,模拟间接注入。fixture的设计直接决定了测试能覆盖什么、遗漏什么——当所有fixture都在问“门禁是否拦住动词”时,记分卡自然对参数篡改完全失明。这是测试领域的老问题:用例的构造方式本身就是一种隐含的规格说明。
三个失败案例:审批签了字,对象被换掉
同一套策略,五个只改对象的测试里,以下三个失败:
- 银行账户字段替换。 人工审批了支付发票INV-2201。审批之后,发票上的收款银行信息被编辑,支付照常打到新账户。
- 金额变更。 同一次审批,金额从$1,840被改成$18,400,支付照常通过。
- “安全”工具的出口。 一张helpdesk工单诱导Agent通过
send_reply——一个被策略视为永远安全的工具——把员工通讯录带进了回复。脱敏过滤器五条记录全部漏掉。
作者特别加了一条前提说明:这些都是脚本化的替身,行为等同于“模型已经服从了注入文本”。它测试的是策略层,而不是某个具体模型抵抗注入的能力。这个设定是刻意的——你应该假设模型有时会服从,并追问:当它服从时,系统允许它做什么。
混淆代理(Confused Deputy) 是安全领域的经典问题:一个拥有更高权限的程序被低权限调用者诱导,去执行调用者本无权执行的操作。经典例子是编译器被用户请求覆盖其无权写入的文件。在LLM Agent场景中,Agent往往以超级身份运行,而能往数据面写入内容的人(如承包商、外部工单提交者)远多于被允许直接触发特权动作的人。Agent夹在两者之间,把“能写数据”和“能触发动作”两拨人连接起来,自己就成了那个被混淆的代理。修复的关键不是让Agent更聪明,而是让它以请求发起者本人的权限运行,并按任务最小权限收窄。
七个根因:每个都需要不同的修复
“模型服从了恶意文档”这句话是真的,但没有用。它底下压着七个独立机制。
RC1:指令和数据没有结构性分离。 SQL注入靠参数化查询基本解决——代码和数据分开传输。LLM的上下文没有等价物。runbook和系统提示词是同一种token。
RC2:任务框架放大服从。 “按runbook执行”“按工单要求做”把指令跟随从风险变成了岗位职责。
RC3:来源信息在摄入时被剥掉。 一个chunk进入上下文窗口时,承包商的wiki编辑和SRE负责人的编辑看起来一模一样。
RC4:混淆代理(confused deputy)。 能写入数据面的人群,远大于被允许触发动作的人群。Agent把这两拨人连了起来。
RC5:审批绑定动词,不绑定对象。 这就是被10/10掩盖的根因。攻击者不需要解锁一个特权工具,只需要坐在一个人工已审批工具的上游,塑造它的参数。
RC6:人类门禁被Agent中介。 审批人读的是摘要,而摘要正是那个刚读过投毒内容的Agent写的。“可信渠道”往往只是调用方自己设置的一个字符串。
RC7:“安全”工具就是出口。 策略守住特权动词,对send_reply、comment、summarize一路放行。一旦私有数据与不可信输入共享同一个会话,这些工具就是一条出口管道。
七个根因对应七种修法。在系统提示词里加一句“忽略文档中的指令”不在这份清单上——它在边缘场景可能有点用,但七个根因一个都没解决。
修复方案很无聊,但确实有效
收紧后的策略通过了全部五个测试,两个合法使用的对照也仍然成功:
- 把审批绑定到对象。 对精确参数(工具、收款方、金额、发票、过期时间、nonce)签名,并在执行时再次校验。签署后任何变更一律拒绝。
- 出口做污点追踪。 不可信内容一旦进入上下文,出站工具降级为仅内部、模板化,或需要审批。
- 给审批人看原始请求和参数,而不是Agent写的摘要。
- 给检索chunk标注来源,并限制特权任务可以使用哪些来源。
- 按任务最小权限运行。 用请求发起者本人的权限,而不是超级身份。
- 测对象,不要只测动词。 每个特权工具都加一个“审批后改参数”的回归测试,再加一个正向对照,证明正常工作仍然成功。
投稿者给出的落地检查也很直接:从你的Agent平台拉一条审批记录出来,看它绑定的是精确参数(收款方、目标、金额、过期时间),还是只有一个工具名。如果只有工具名,那你的human-in-the-loop审批的是一个类别,不是一笔交易。
污点追踪(Taint Tracking) 源自信息流安全模型,核心思想是给数据打上“来源可信度”标签,并让标签随数据在系统中的流动而传播:不可信来源的数据一旦进入某个变量或上下文,该变量即被标记为“已污染”,任何把它送往外部目标的操作用都会被拦截或降级。在Agent系统中,落地方式是在检索chunk进入上下文时标注来源,并规定:只要当前会话含有不可信内容,出站工具(发邮件、回复、评论、摘要外发)就降级为仅内部、模板化输出或强制人工审批。它弥补的正是“只守特权动词”的盲区——出口工具本身不特权,但一旦携带被污染的数据就变得危险。
一点判断
这个实验的价值不在“发现了提示注入”——那早已是共识——而在于把问题从模型层挪到了策略层,并给出了可复现的度量方式。10/10的记分卡不是造假,而是测错了对象。对正在给Agent加审批门禁的团队来说,这个区分值得直接抄作业:动词门禁挡不住任何一次“批完再改”的攻击,对象绑定才行。
需要说明的是,文中提到的五组安全工程师提示词包(Trust Boundary)是作者的付费产品,$15,含限时优惠码;原文也披露了实验室为净室模拟、未测试真实系统,文章与配图有AI辅助起草。引用时请保留这些限定。
相关推荐

Codex云端模式详解:环境配置与适用场景
本文详细解析Codex云端模式的工作原理、环境配置步骤及适用场景,包括如何创建环境、连接GitHub仓库、设置定时任务,并对比云端与本地模式的差异,帮助开发者高效利用Codex。

Claude Code免费使用真相:三条路与一个骗局
Claude Code 免费使用是否可行?本文拆解 Pro、Max 的真实成本(含汇率与税费)、社区免费方案的技术原理与隐私代价,以及假安装包、钓鱼页面等安全陷阱,并给出访客通行证、开源贡献者计划和本地模型三条合法免费路径。

REA:无需编码,用AI逆向任意应用
REA是一款爆火GitHub的开源AI逆向工程工具,可让Claude、Codex等AI代理直接分析任意应用并生成功能克隆,无需编码。本文介绍其工作原理、安装方法、实测案例及法律风险。