跳到主要内容

RBAC 对 AI Agent 来说还不够:一种实用的授权模型

· 阅读需 13 分钟
Tian Pan
Software Engineer

如今,大多数构建 AI agent 的团队都将授权视为事后才考虑的事情。他们接入一个 OAuth 令牌,给 agent 分配与触发它的用户相同的权限范围(scopes),然后就大功告成了。然而,几个月后,他们会发现一段被操纵的提示词导致 agent 窃取了文件,或者一个受损的工作流在连接的服务中悄无声息地提升了权限。

问题不在于 RBAC 不好。而是在于 RBAC 是为具有稳定工作职能的人类设计的,而 AI agent 既不稳定也不是人类。在一个对话回合中,agent 的“角色”可能从只读研究转变为具备写入能力的代码执行。静态角色无法表达这一点,这种不匹配创造了一个可预见的漏洞攻击面。

主客体混淆问题

根源问题在经典安全理论中有一个名称:混淆代理问题(confused deputy problem)。混淆代理是指一个拥有特权的程序被权限较低的调用者欺骗,从而滥用其权限。对于 AI agent 来说,这并非特例 —— 而是默认架构。

它的典型工作方式如下:用户向平台进行身份验证,平台代表用户发布一个 agent,该 agent 继承了用户具有全部权限范围的 OAuth 令牌。现在,这个 agent 拥有了访问电子邮件、日历、云存储、GitHub 和 Slack 的权限 —— 并非因为它需要所有这些,而是因为用户在早些时候恰好授予了所有这些权限。当提示词注入攻击引导 agent 执行恶意操作时,目标系统看到的是一个完全授权的调用。由于从技术上讲 agent 拥有权限,因此没有什么可以阻拦它。

多 agent 系统放大了这一点。当一个编排器将子任务委派给专门的 agent 时,每一次跳转都可能在没有显式授权审查的情况下传播原始用户的环境权限集。单个受损的 agent 就会成为跨整个图谱进行横向移动的向量。

修复方法在概念上很简单,但在架构上要求很高:将 agent 视为独立的身份。给它一个独特的 OAuth 客户端 ID。将其访问范围限制在当前任务所需的范围内。让该访问权限在任务结束时过期。

为什么仅靠 RBAC 会失效

基于角色的访问控制(RBAC)通过为外部主体(principal)分配角色,然后在配置时将角色映射到权限来工作。这种模型非常适合人类 —— 开发人员角色授予对存储库的读/写权限,但不授予数据库管理权限。角色反映了在组织时间尺度上变化的稳定工作职能。

AI agent 在不同的时间尺度上运行。单个 agent 可能会执行只读分析,然后建议架构更改,接着执行代码部署,所有这些都在一个 10 分钟的任务内完成。通过角色分配来跟上这些转换会产生两种失败模式:

  • 过度授权的单一角色: 授予一个涵盖 agent 可能需要的每一项操作的角色。这是常见的路径,它完全违背了访问控制的目的。
  • 角色抖动: 在每个子任务中更换角色。这会使审计日志充斥着角色变更事件,并在并发工作流中产生竞态条件。

在 agent 可以以机器速度在外部服务上发起写入操作的系统中,这两种结果都是不可接受的。

基于属性的访问控制(ABAC)通过将授权决策移动到运行时来解决这个问题。ABAC 策略引擎不再询问“这个主体拥有什么角色?”,而是询问“考虑到当前的所有上下文 —— 谁在请求什么资源、在什么条件下、在什么时间 —— 是否应该允许此操作?”策略可以表达如下规则:仅当任务上下文中存在先前的代码审查批准时,agent 才能写入此存储库。RBAC 无法表达这种关系,而 ABAC 可以。

由此产生的实际模式是一种混合体:RBAC 设置外部边界,ABAC 执行内部约束。 RBAC 规则规定“代码生成”类型的 agent 永远不能删除生产数据库。ABAC 策略则规定,这个特定的 agent 在这个特定的任务中,在接下来的 8 分钟内只能读取 /tmp 目录下的文件。单独任何一层都无法提供正确的粒度;它们结合在一起既涵盖了结构上的不变性,又涵盖了动态的逐任务约束。

最小特权工具范围界定

除了访问控制模型本身,工具接口是权限缩小或扩张的主要场所。

典型的错误是构建功能宽泛的工具。一个名为 manage_github 且接受任意 GitHub API 调用的工具既灵活又易于构建。它也是一个具有写入权限的风险点(footgun)。当 agent 需要开启一个 PR 时,它使用该工具。当提示词注入告诉它删除分支时,它也使用该工具 —— 而你的授权层永远不会看到权限边界被跨越。

有效的替代方案是窄工具:open_pull_requestread_filelist_open_issues。每个工具都以特定的权限范围编码特定的操作。工具接口成为了权限接口。一个工具集中只有 read_file 的 agent 无法删除分支,无论提示词怎么说,因为在其可用的动作空间中不存在这种能力。

由此得出几条实用原则:

  • 将工具默认设置为只读。仅当任务明确需要时才添加具备写入能力的工具,并在任务完成后撤销。
  • 将授权上下文推送到服务器,而不是提示词中。组织 ID、用户 ID 和权限范围来自后端的身份验证会话令牌 —— 而不是来自可能被覆盖的 agent 上下文窗口。
  • 与其使用一个通用的端点,不如倾向于使用几个专注于特定任务的工具。三个各司其职的工具比一个带有一个由 agent 解释的“模式”参数的工具更容易审计和限定范围。

OWASP 针对 Agentic 应用的十大漏洞(Top 10)将工具滥用和权限提升识别为关键风险,特别点名了那些接收过度授权工具并利用它们执行非预期操作的 agent。缓解措施是架构层面的:设计工具表面,使非预期操作变得不可能,而不仅仅是未经授权。

基于任务的凭据签发

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates