安全审查称智能体(Agent)“代表”(on behalf of)用户操作。OAuth 令牌却有不同的说法,而审计日志也支持令牌的说法。
语言上的一点微小差别,在架构层面起到了意想不到的作用。“代表”(On behalf of)是安全审查在试图描述一种委派安排时使用的语言,即智能体是一个可识别的委派对象,并受此身份约束。“作为”(Act as)则是运行时的行为,此时智能体持有的令牌与用户本人的令牌完全一致,因此在任何下游系统看来,智能体就是用户。这两个短语描述了完全不同的威胁模型。典型的企业级 OAuth 集成交付的是后者,但宣传的却是前者。
鸿沟在第一次出问题时显现。一段提示词注入(Prompt-injected)指令通过一封要求智能体总结的邮件传达。智能体执行了注入指令中的操作。审计日志将该用户记录为作者。调查最初会针对该用户进行人事审查,然后才会有人质疑是否有智能体参与其中,因为运行时的踪迹中没有任何信息表明存在智能体。
审查批准了委派,令牌批准了冒充
在我见过的所有集成中,这种模式都是一致的。产品团队搭建了一个 OAuth 流程,向智能体授予了一个限定在用户身份范围内的令牌。安全审查阅读了集成规范,看到了“智能体代表用户操作”,并基于下游系统能够区分委派操作和直接操作的假设批准了它。但从 IdP 返回的令牌是一个用户形态的令牌,其形状与用户直接登录时持有的令牌完全一致。
下游系统并不在对话范围内。日历服务、邮件服务、文档存储——它们每一个都会验证令牌,将持票人识别为用户,然后继续执行。令牌上没有任何字段说明“此操作是由智能体发起的”。下游服务也不需要读取任何特定的请求头。审计追踪按用户 ID 记录操作,因为这是请求携带的唯一身份。安全审查批准的架构意图只存在于设计文档中,而没有体现在任何传输格式里。
这正是 RFC 8693 的 actor (act) 声明(claim)旨在弥补的差距。该规范定义了一个 JWT 字段,旨在“在 JWT 中提供一种方式来表达已发生委派,并识别获得授权的执行方”。委派链可以嵌套——最外层的 act 是当前的执行者,内部的声明则保留委派链。针对 AI 智能体的 OAuth “代表”扩展的 IETF 草案以此为基础,增加了将智能体身份贯穿授权屏幕并进入所颁发令牌的参数。但这些机制只有在下游系统读取它们时才起作用,而 2026 年的大多数生产环境服务并不会读取。
实际后果是,除非令牌机制强制执行,否则“代表”只是一个安全主张,而非技术现实。一个向智能体授予用户形态令牌的团队,实际上是将用户的全部身份交给了一个运行时,而该运行时的决策是由一个并不知道自己在冒充他人的模型做出的。
提示词注入将冒充演变为安全事件
当集成运行良好时,这种差距是隐形的。智能体按照用户的要求行事,审计追踪看起来也像是用户做的,这在广义上是准确的。架构的失效模式在智能体第一次执行用户未要求的操作时显现——而在 2026 年,触发这种模式最可靠的方式就是提示词注入。
这种威胁模型已广为人知。智能体在工作中读取不可信的内容——邮件正文、文档、日历邀请或网页。内容中包含一条指令。模型将该指令视为其工作上下文的一部分并遵循它。指令可以要求智能体发送邮件、共享文档、安排会议,或者调用该智能体令牌作用域内的任何其他工具。由于智能体的令牌是用户形态的,它会毫无障碍地授权所有这些操作。
三个步骤接踵而至:
智能体利用用户的身份执行注入的操作。
下游系统将该操作记录为用户发起的。
用户的经理或安全团队查看审计追踪,并将用户视为执行者。
调查现在从错误的地方开始了。用户因该操作受到质疑。用户不记得这件事,因为他们确实没做。要确认有智能体参与,取证工作需要将审计日志与智能体执行追踪进行关联,而这种关联只有在智能体执行追踪存在、被保留,并且能够通过用户 ID 和时间戳以外的手段与下游事件相关联时才可能实现。许多团队在事件发生期间才发现他们无法进行这种关联,因为智能体的工具调用被记录在一个其保留政策未预见到取证用途的系统中。
当操作具有破坏性时,损害会进一步加剧。智能体发送的邮件是真实的邮件。智能体共享的文档真的被共享了。补救工作不仅仅是清理审计日志,还要清理已经离开系统的操作所带来的后果。爆炸半径(Blast radius)是用户拥有的全部权限,因为智能体继承了全部权限。
Token 应该体现出评审所说的内容 修复方案是结构性的,且必须发生在 Token 层。那种“Agent 代表用户执行操作”的架构声明,必须在执行访问决策的地方(即下游系统的鉴权检查)真实生效。有三种模式可以弥补这一差距,其中第一种是不可协商的。
在每一个下游调用中都具备独立的 Agent 身份。 Agent 拥有自己的身份,独立注册并拥有自己的凭证。提交给下游系统的 Token 同时携带 Agent 的身份和用户的身份——Agent 作为执行者(Actor),用户作为主体(Subject)。这就是 RFC 8693 的 act 和 subject Claim 所建模的内容,也是 IETF 为 Agent 代理(on-behalf-of-for-agents)草案在授权流中标准化的内容。下游系统的审计日志会同时记录两者,取证审查可以分别回答“谁执行了操作”和“为谁执行”这两个独立的问题。在调查中,用户不再是唯一的信号。
下游端强制执行 Agent Claim。 想要参与“代为执行(on-behalf-of)”契约的下游服务,必须将 Agent Claim 的缺失视为一个有意义的信号。一个没有 act Claim 的请求要么是直接的用户操作,要么是不符合策略的集成。服务可以要求任何从 Agent 工具端可触达的路径必须包含 act 字段,并拒绝缺乏该字段的请求。这构成了闭环:如果没有强制执行,Agent 就可以提交一个“用户形态”的 Token,而架构意图将再次变得无法执行。
缩小作用域的委派 Token,而非全量身份继承。 正确使用的 Token 交换(Token exchange)是权力的缩减,而非权力的转移。每一次委派跳转都应该产生一个比前一个 Token 作用域更窄的新 Token。一个需要代表用户发送邮件的 Agent 应该接收到一个作用域限定为 mail.send 且仅针对任务所需特定收件人集的 Token,而不是用户的完整 mail.* 作用域。这样,提示词注入(Prompt injection)的爆炸半径就会被限制在任务作用域内,而不是用户的全部权限。作用域塌陷问题——即 Agent 即使在实际任务只需要一小块权限时也继承了发起用户的全部权限——是导致“冒充模式”变得危险的原因;而缩小作用域的 Token 则使其变得可控。
第四种模式是运营层面的,值得一提:审计日志增强。 Agent 的执行追踪应该能够通过双方都记录的请求 ID 或关联 Token 与下游审计事件相关联。在设计阶段实施这一点的成本很小,但在发生事故期间实施的成本却是巨大的。
评审本该使用的威胁模型 评审之所以失败,是因为它读对了文字,却批准了错误的架构。“代为执行”被视为对集成意图的描述,而它本应被视为有线格式(Wire format)必须强制执行的一种属性。本该提出的正确问题不是“Agent 是否代表用户执行操作?”——设计文档说是,且设计文档是正确的。正确的问题应该是:“如果 Agent 做了用户没有要求的事情,审计日志会记录是谁做的?”
这个问题有一个二元的答案。审计日志要么能区分 Agent 和用户,要么不能。如果不能,那么无论设计文档如何称呼它,这种集成就是“冒充(Impersonation)”,适用的威胁模型是“用户已经赋予了 Agent 运行时以其身份执行操作的能力,且在事后没有任何架构手段来恢复这种区别”。提示词注入并不是达到该威胁模型的唯一途径——Agent 的 Bug、模型幻觉、配置错误的工具以及被破坏的检索源都会导致同样的结果——但提示词注入是攻击者按需驱动 Agent 达到该模型的最可靠方式。
到了 2026 年,随着 Agent 相关的 CVE 数量逐年激增,且大多数事件都追溯到作用域过大且有效期过长的凭证,这个问题不再是假设性的。基于“用户形态 Token”模式构建的团队交付了一个他们无法进行取证调试的运行时,以及一个如果不重写集成无法防御的威胁模型。而基于独立 Agent 身份、双主体 Token 和下游强制执行 act Claim 构建的团队,则交付了一个审计日志真实、爆炸半径受限且“代为执行”真正符合评审含义的运行时。
今天要做的工作是根据上述问题重新审视你已经交付的集成。对于你产品运行的每个 Agent,查看它提交给工具的 Token。然后查看这些工具的审计日志,询问它们记录的是“此操作由 Agent 代表用户执行”,还是仅仅记录“此操作由用户执行”。如果是后者,你进行的安全性评审批准了一个并不存在的系统。实际存在的系统距离将这一差距公之于众,只差一次提示词注入。
会员专享
余下内容仅对会员开放。 会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
— 完整文章,包含未公开存档的部分 — 可落地的工作框架,附带权衡与决策依据 — 新文章抢先看,先于公开发布 登录以继续阅读→ 随时取消 · 一次订阅,畅读全部