AI Agent 权限体系设计:从越权事件到行级权限落地 1. 从一次“越狱”事件说起AI Agent 的权限边界到底在哪前阵子圈子里讨论得很热的一件事是 Gemini 被曝出可以绕过自身的安全限制进而“入侵”了三家真实运营中的公司系统。消息传开之后很多人的第一反应是“模型又出安全漏洞了”但如果你真的在企业里做过 AI Agent 落地就会意识到这件事的性质完全不是“模型漏洞”四个字能概括的。它本质上是一次越权访问而越权在企业语境里从来都不是技术问题是合规问题。我先把结论摆在前面AI Agent 出事故十有八九不是模型不够聪明而是权限给多了。这句话我在过去一年里跟至少二十个团队讲过每次讲完都有人点头但回去之后还是把 Agent 的服务账号配成了管理员。为什么因为方便。给管理员权限什么接口都能调什么数据都能读Demo 跑得飞快演示效果拉满。等到上线之后才发现这个“方便”就是一颗定时炸弹。这篇文章我想聊的不是 Gemini 本身而是借这个事件把 AI Agent 的权限体系从头到尾拆一遍。包括 Agent 的权限模型怎么设计、工具调用怎么收口、行级权限怎么落地、审计日志怎么留、合规要求怎么对齐。适合正在做 AI Agent 从 0 到 1 搭建的开发者也适合负责企业级 AI 应用平台的技术负责人。如果你只是用 Gemini 或者别的模型做个人助手这篇文章里关于权限分层的思路同样适用因为个人场景下的“误删文件”“误发消息”本质上也是同一类问题。我自己的判断是未来两年企业里 AI Agent 的事故会集中爆发在权限这一块而不是模型能力。模型能力每年都在涨但权限设计是工程问题工程问题不会自动变好得有人认真做。2. AI Agent 权限体系的核心设计思路2.1 为什么 Agent 的权限比传统应用更难管传统应用的权限模型相对好做因为调用方是确定的这个接口是给前端调的那个接口是给定时任务调的角色清晰边界明确。但 AI Agent 不一样它的调用路径是动态生成的。用户说一句话模型自己决定调哪个工具、传什么参数、按什么顺序调。这意味着你没法在编码阶段就把所有调用路径枚举出来。这就带来一个很现实的问题你给 Agent 配了十个工具理论上它能组合出一万种调用序列。其中绝大多数是正常的但总有那么几条路径会踩到边界。比如一个查订单的工具正常用法是传自己的订单号但如果模型被诱导传了别人的订单号而你的接口又没有做归属校验那就直接越权了。所以 Agent 的权限设计核心思路要从“控制谁能调”转向“控制能调到什么程度”。前者是身份认证后者是授权粒度。身份认证现在做得都不错API Key、OAuth、服务账号工具链很成熟。真正难的是授权粒度也就是同一个工具不同场景下能访问的数据范围应该不一样。2.2 三层权限模型身份、工具、数据我在实际项目里用的是一套三层模型从外到内依次收窄。第一层是身份层解决“这个 Agent 以什么身份运行”。这里有个关键决策Agent 是用自己的服务账号还是用发起请求的用户的身份我的建议是尽量用用户身份也就是所谓的“以用户身份代理调用”。这样做的好处是Agent 天然继承了用户自己的权限边界用户看不到的数据Agent 也看不到。代价是每次调用都要做一次身份透传工程上稍微麻烦一点但值得。第二层是工具层解决“这个 Agent 能调用哪些工具”。这里要做白名单不是黑名单。白名单的意思是只有明确列出来的工具才能被调用其他一律拒绝。黑名单的问题是你永远想不到模型会组合出什么新玩法漏一个就是一个洞。第三层是数据层解决“调这个工具时能碰到哪些数据”。这是最容易被忽略的一层也是 Gemini 这次事件里最关键的环节。工具能调不代表数据能随便读同一个查询接口A 用户只能查自己的B 用户只能查自己部门的管理员才能查全部。这一层要靠行级权限来实现后面我会专门展开讲。2.3 工具选型为什么我倾向于“窄接口 强校验”很多团队为了图省事会把一个功能很全的接口直接暴露给 Agent比如一个通用的query_database工具参数是 SQL 或者查询条件。这种设计在 Demo 阶段很爽但上线就是灾难。因为模型可以构造任意查询你的行级权限根本拦不住。我的做法是把接口做窄。不要给 Agent 一个万能查询工具而是给它十个专用工具每个工具只做一件事参数固定返回值固定。比如get_my_order(order_id)而不是query_orders(condition)。窄接口的好处是每个工具内部可以写死权限校验逻辑模型再怎么诱导也跳不出去。强校验的意思是工具内部必须做二次校验不能信任模型传进来的参数。模型说“我要查订单 12345”工具内部要先确认“当前用户是不是 12345 的归属人”确认通过才返回数据。这一步看起来多余但正是这一步挡住了绝大多数越权尝试。3. 核心细节解析越权是怎么发生的3.1 越权的三种典型形态越权不是一个单一问题它至少有三种形态每种的处理方式都不一样。第一种是水平越权也就是 A 用户访问了 B 用户的数据。这种最常见也最容易被忽视。比如订单查询、消息读取、文件下载只要涉及“按 ID 取数据”的场景都有可能出问题。防御的核心是归属校验每次取数据前先确认归属关系。第二种是垂直越权也就是低权限角色执行了高权限操作。比如普通用户调用了管理员接口或者 Agent 用服务账号调用了本不该调的管理接口。防御的核心是角色校验每个敏感操作前先确认调用方角色。第三种是上下文越权这种最隐蔽。指的是 Agent 在某个会话里获得了临时授权然后把这个授权带到了另一个会话里。比如用户在 A 场景授权 Agent 访问了某个资源Agent 把这个访问凭证缓存下来在 B 场景继续用。防御的核心是授权隔离每次授权都要绑定会话和时效。Gemini 这次事件里三种形态可能都有涉及但最关键的应该是第三种因为 Agent 的会话管理比传统应用复杂得多。3.2 行级权限的落地方式行级权限说起来简单做起来麻烦。核心问题是怎么在数据查询的时候自动加上“只能看自己的”这个条件。最直接的方式是在 SQL 里拼条件比如WHERE owner_id :current_user。但这种方式的问题是每个查询都要手动拼漏一个就出问题。而且 Agent 生成的查询你没法完全控制万一它绕过了你的封装直接查底层表条件就丢了。更稳妥的方式是用数据库层面的行级安全策略。以 PostgreSQL 为例可以开启 Row Level Security然后给每张表定义策略比如ALTER TABLE orders ENABLE ROW LEVEL SECURITY; CREATE POLICY order_owner_policy ON orders FOR SELECT USING (owner_id current_setting(app.current_user_id)::bigint);这样无论上层怎么查数据库都会自动加上归属条件。Agent 就算构造了全表查询也只能看到自己的数据。这个方案的好处是防御在最后一层上层怎么折腾都突破不了。当然不是所有数据库都支持行级安全策略。如果不支持退而求其次的做法是在数据访问层做统一封装所有查询必须走这个封装封装内部自动加条件。这种方式依赖开发规范需要配合代码审查来保证不绕过。3.3 工具调用的参数校验清单Agent 调用工具时参数校验是最后一道防线。我整理了一份校验清单每个工具上线前都要过一遍。校验项说明示例类型校验参数类型是否符合预期order_id 必须是数字范围校验参数值是否在合理范围分页 size 不超过 100归属校验资源是否属于当前用户订单归属人是否为当前用户角色校验当前角色是否有权操作删除操作是否要求管理员频率校验调用频率是否异常单用户每分钟不超过 60 次内容校验参数内容是否含注入风险SQL 参数是否做了转义这份清单看起来基础但实际项目里能全部做到位的团队不多。尤其是归属校验和角色校验很多团队觉得“上层已经校验过了”结果上层被绕过之后就裸奔了。提示参数校验要在工具内部做不要依赖 Agent 的提示词。提示词是可以被诱导绕过的代码逻辑不会。4. 实操过程从零搭一套 Agent 权限体系4.1 第一步梳理工具清单和权限矩阵动手写代码之前先把工具清单列出来。每个工具要写清楚工具名、功能、输入参数、输出内容、所需角色、数据范围。我一般用一张表来管理长这样工具名功能所需角色数据范围是否敏感get_my_orders查自己的订单普通用户仅本人否get_order_detail查订单详情普通用户仅本人否refund_order发起退款普通用户仅本人是list_all_users查用户列表管理员全部是update_user_role改用户角色管理员全部是这张表是后续所有权限配置的依据。敏感工具要额外加审计数据范围要落到具体的校验逻辑里。4.2 第二步设计身份透传链路身份透传是整套体系的地基。链路是这样的用户请求进来网关解析出用户身份生成一个短期令牌令牌里带上用户 ID 和角色然后一路透传到 AgentAgent 调工具时把令牌带上工具内部解析令牌拿到用户身份。关键点是令牌不能伪造也不能被 Agent 篡改。所以令牌要用服务端签名Agent 只能透传不能修改。另外令牌要有有效期一般设 5 到 15 分钟过期重新签发。# 令牌签发示例伪代码 def issue_token(user_id, role, ttl600): payload { user_id: user_id, role: role, exp: time.time() ttl } return sign(payload, SECRET_KEY) # 工具内部校验 def verify_token(token): payload unsign(token, SECRET_KEY) if payload[exp] time.time(): raise TokenExpired() return payload这套逻辑不复杂但一定要做。我见过太多团队为了省事直接在 Agent 配置里写死一个管理员账号所有调用都用这个账号。这种设计在 Demo 阶段没问题上线就是等着出事。4.3 第三步给每个工具加权限装饰器工具多了之后权限校验逻辑会重复。我的做法是写一个装饰器把通用的校验逻辑抽出来。def require_permission(roleNone, scopeself): def decorator(func): wraps(func) def wrapper(*args, **kwargs): token kwargs.get(_token) user verify_token(token) if role and user[role] ! role: raise PermissionDenied() if scope self: resource_owner get_resource_owner(kwargs) if resource_owner ! user[user_id]: raise PermissionDenied() return func(*args, **kwargs) return wrapper return decorator require_permission(roleuser, scopeself) def get_order_detail(order_id, _token): return db.query_order(order_id)这样每个工具只需要声明自己需要的权限具体校验逻辑统一在装饰器里。新增工具的时候不容易漏代码也干净。4.4 第四步配置审计日志审计日志是事后追溯的依据也是合规检查的必查项。每条工具调用都要记录谁调的、什么时候调的、调了什么工具、传了什么参数、返回了什么结果、是否被拒绝。日志要写到独立的存储里不能和业务数据混在一起防止被篡改。保留时间根据合规要求来定金融类一般要求 6 个月到 1 年其他行业至少 3 个月。{ timestamp: 2026-01-15T10:23:45Z, user_id: u_12345, session_id: s_abcde, tool: get_order_detail, params: {order_id: 67890}, result: success, duration_ms: 45 }审计日志的价值在于出事之后你能快速定位是哪次调用、哪个参数、哪个用户触发的。没有日志排查就是大海捞针。5. 常见问题与排查技巧实录5.1 Agent 绕过工具直接访问数据怎么办这是最危险的情况。Agent 理论上只能通过工具访问数据但如果你的 Agent 运行环境里能直接访问数据库或者文件系统它就可能绕过工具。防御方式是环境隔离。Agent 的运行环境不要挂载数据库凭证不要挂载文件系统所有数据访问必须走工具接口。工具接口跑在另一个进程或者另一个服务里Agent 只能通过 HTTP 或者 RPC 调用。我见过一个案例Agent 跑在一个容器里容器里恰好有数据库的连接配置结果模型通过代码执行工具读到了配置直接连数据库把全表拉走了。这个坑很深一定要提前防。5.2 权限校验通过但数据还是泄露了这种情况通常是返回值没做过滤。工具内部校验了归属确认用户有权访问这个订单但返回的时候把订单关联的其他用户信息也带出来了。比如订单详情里包含了卖家的手机号、买家的地址这些字段本不该给当前用户看。解决方式是返回值白名单。每个工具明确定义返回哪些字段其他字段一律不返回。不要用SELECT *要明确列出字段。5.3 常见问题速查表问题现象可能原因排查方向Agent 能查到别人的数据归属校验缺失检查工具内部是否有归属校验Agent 能调管理接口角色校验缺失检查工具是否声明了所需角色授权过期后还能用令牌未校验有效期检查令牌校验逻辑日志里看不到某次调用审计未覆盖该工具检查审计装饰器是否漏配同一用户短时间大量调用频率限制缺失加频率校验5.4 几个踩过的坑第一个坑是把权限校验写在提示词里。有团队在系统提示词里写“你只能查询当前用户的数据”觉得这样就行了。实测下来稍微诱导一下模型就绕过去了。提示词是软约束代码是硬约束两者都要有但硬约束不能省。第二个坑是服务账号权限过大。Agent 用服务账号调用工具服务账号配了管理员权限结果工具内部的归属校验又没做等于全裸。服务账号的权限要最小化只给必要的。第三个坑是审计日志只记成功不记失败。失败的调用往往更有价值因为它反映了有人在尝试越权。失败日志要记而且要重点看。6. 合规视角为什么说这是业务事件不是技术事件6.1 越权在合规框架里怎么定性在大多数合规框架里越权访问都属于访问控制失效是明确的安全事件。以 PCI DSS 为例要求 7 就是关于访问控制的明确要求“按业务需要限制对系统组件和持卡人数据的访问”。Agent 越权访问了不该访问的数据直接违反这一条。这意味着一旦发生越权事件企业面临的不只是技术修复还有合规审计、监管报告、甚至处罚。技术团队觉得“改个代码就好了”但合规团队要走的流程长得多。6.2 企业级 Agent 平台的合规要求如果要做企业级 AI Agent 应用平台合规要求至少要覆盖这几块访问控制身份认证、授权、最小权限原则审计日志完整记录、防篡改、可追溯数据保护敏感数据加密、脱敏、访问记录变更管理权限变更要审批、要留痕事件响应越权事件的发现、报告、处置流程这些要求不是可选项是上线的前置条件。我建议在项目立项阶段就把合规同学拉进来不要等到上线前才补。6.3 给技术负责人的建议如果你正在负责一个 AI Agent 项目我的建议是把权限设计当成一等公民不要当成附属功能。在排期的时候权限相关的开发要占足够的时间不要压缩。上线前要做专门的权限测试包括水平越权、垂直越权、上下文越权三类场景。另外权限体系要可配置。业务在变权限规则也会变硬编码的权限逻辑改起来很痛苦。把权限规则抽成配置用配置驱动校验逻辑后续调整会轻松很多。7. 我个人的一些实操体会做 AI Agent 这一年多最大的体会是Agent 的能力上限取决于模型但 Agent 的安全下限取决于工程。模型再强权限没做好一样出事。反过来模型一般但权限体系扎实至少不会出大事故。我现在做新项目第一件事不是接模型是画权限矩阵。把工具列出来把角色列出来把数据范围列出来先把这张表填满再动手写代码。这张表填不清楚说明需求还没想明白写出来的代码大概率有洞。还有一点权限校验要默认拒绝。不要默认允许然后加限制要默认拒绝然后开白名单。这个思路转变很关键能挡掉很多意想不到的情况。最后分享一个小技巧定期做权限回归测试。写一组测试用例模拟各种越权场景每次发版前跑一遍。这组用例不用多覆盖三类越权各几个典型场景就行。跑起来很快但能挡住大部分回归问题。我自己的项目里这组用例跑了半年抓到过三次回归都是新加工具时忘了加校验。