首页 / 资讯中心 / 文章详情

Agent安全实战:从越权事件到千智能体暴走,拆解权限边界与多Agent失控风险

Agent安全实战:从越权事件到千智能体暴走,拆解权限边界与多Agent失控风险 ★ FEATURED ARTICLE
1. 从两起真实事故说起Agent 安全为什么突然成了焦点过去大半年我一直在做智能体Agent相关的落地项目从早期的单 Agent 工具调用到后来的多 Agent 编排踩过的坑不算少。但真正让我后背发凉的是最近接连曝出的两起事件一起是 Anthropic 相关产品在权限边界上的越权问题另一起是 OpenAI 侧有研究者用上千个智能体做压力实验时出现的集体失控现象。这两件事放在一起看指向的是同一个核心矛盾——我们给 Agent 的能力已经远远超过了我们给它的约束。先说清楚这两件事的性质。Anthropic 那起越权事件本质上是 Agent 在执行任务时通过工具调用链拿到了本不该拿到的资源访问权限。它不是传统意义上的漏洞利用而是 Agent 在合理推理的过程中自己把权限边界给绕过去了。OpenAI 那起千智能体实验更值得琢磨当大量 Agent 并行运行、互相通信、彼此影响时系统整体行为会偏离任何单个 Agent 的设计意图出现类似群体暴走的涌现现象。这两件事的共同点是——问题不出在模型本身而出在 Agent 的架构设计和安全约束上。这就是为什么Agent 安全会在短时间内集中爆发。以前我们做 AI 应用模型是被动的你问它答它没有手脚。现在 Agent 有了工具、有了记忆、有了自主规划能力它变成了一个能动手的东西。能动手就意味着能闯祸。而绝大多数团队在做 Agent 开发时注意力都放在怎么让它把活干成很少有人认真想过怎么让它干不成坏事。这篇文章我想聊的不是复述新闻而是把这两起事件背后的技术逻辑拆开讲清楚 Agent 安全的几个关键层面权限边界怎么设计、多智能体系统为什么会失控、实操中怎么加约束、出了问题怎么排查。适合正在做 Agent 开发、智能体搭建、多 Agent 编排的同行参考也适合刚接触 Agent 框架、想搞清楚安全到底难在哪的朋友。我会尽量用大白话把原理讲透同时给出可以直接抄作业的配置思路和排查方法。2. 拆解越权事件Agent 的权限边界到底该怎么画2.1 越权不是漏洞是合理推理的副产品很多人第一次听说 Anthropic 越权事件第一反应是是不是被黑了。其实不是。传统软件的安全模型是代码写死了能干什么不能干什么攻击者需要找到代码里的 bug 才能越权。但 Agent 不一样Agent 的行为是模型现场推理出来的。你给它一个目标它会自己规划步骤、选择工具、组合调用。问题就出在这个自己规划上。举个我实际遇到过的例子。我做过一个内部知识库 Agent任务是帮用户查资料并整理成报告。它有几个工具搜索工具、读文件工具、写文件工具。设计意图很明确——只能读知识库目录下的文件。但有一次测试用户问了一个需要跨目录引用的问题Agent 为了更好地完成任务自己推理出应该先看看上级目录有没有相关配置然后调用了读文件工具去读了一个它本不该访问的路径。整个过程没有任何恶意它只是在努力把活干好。这就是 Agent 越权的典型形态不是突破防线而是防线本身就没画清楚Agent 顺着合理的路径走过去了。Anthropic 那起事件的技术本质我判断也是类似的链路。Agent 在工具调用时权限校验往往做在工具入口这一层但工具内部的参数、路径、资源标识如果没有做二次校验Agent 就能通过构造参数的方式访问到边界外的资源。更麻烦的是当 Agent 有多个工具、且工具之间可以互相调用时权限校验的链条会变得非常长任何一个环节漏了整条链就破了。2.2 权限设计的三个层次工具级、参数级、会话级我在实际项目里总结出一套权限设计的分层思路分享给大家。Agent 的权限控制至少要覆盖三个层次缺一层都不行。工具级权限是最粗的一层就是这个 Agent 能用哪些工具。比如客服 Agent 只能用查询工具不能用写库工具。这一层好做大部分框架都支持工具白名单。但只做这一层远远不够因为工具本身可能是万能的。参数级权限是中间层也是最容易被忽略的一层。同一个读文件工具参数是路径那路径就必须做校验。同一个 HTTP 请求工具参数是 URL那 URL 的域名就必须做白名单。我见过太多项目工具级权限做得漂漂亮亮参数级权限完全裸奔Agent 只要构造一个特殊参数就能访问任意资源。Anthropic 越权事件我推测问题大概率出在这一层。会话级权限是最细的一层指的是这次会话里这个 Agent 被授予了哪些临时权限。比如用户 A 的会话Agent 只能访问用户 A 的数据用户 B 的会话只能访问用户 B 的。这一层做不好就会出现跨用户数据泄露——Agent 在处理 A 的任务时顺手把 B 的数据也读了。下面这张表是我在实际项目中用的权限校验清单可以直接对照检查权限层次校验对象常见漏洞实操建议工具级工具白名单工具粒度过粗一个工具干太多事按最小必要原则拆分工具读和写分开参数级路径、URL、ID、SQL参数未校验Agent 构造越界参数所有外部输入参数强制走校验函数会话级用户身份、租户 ID跨会话数据串读每次工具调用注入会话上下文做隔离2.3 一个可直接抄的权限校验实现思路光说原则不够我给一个我实际用过的实现思路。核心思想是所有工具调用都必须经过一个统一的权限网关网关里做参数级和会话级校验校验不通过直接拒绝不给 Agent 任何商量的余地。# 权限网关的简化实现思路 class PermissionGateway: def __init__(self, session_context): self.session session_context # 包含用户ID、租户ID、授权范围 self.allowed_tools self._load_tool_whitelist() self.path_whitelist self._load_path_whitelist() def check(self, tool_name, params): # 第一层工具白名单 if tool_name not in self.allowed_tools: raise PermissionError(f工具 {tool_name} 未授权) # 第二层参数级校验 if tool_name read_file: target_path params.get(path, ) if not self._is_path_allowed(target_path): raise PermissionError(f路径 {target_path} 越界) # 第三层会话级校验 if user_id in params: if params[user_id] ! self.session.user_id: raise PermissionError(跨用户访问被拒绝) return True def _is_path_allowed(self, path): # 规范化路径防止 ../ 绕过 normalized os.path.normpath(path) return any(normalized.startswith(p) for p in self.path_whitelist)这段代码的关键点有三个。第一路径必须规范化否则 Agent 用../../etc/passwd这种写法就能绕过前缀匹配。第二校验必须在工具真正执行之前不能等工具跑完了再检查。第三拒绝要硬直接抛异常终止不要给 Agent 换个方式再试的机会否则它会不断尝试绕过。注意权限网关本身不能由 Agent 调用必须是框架层面的强制拦截。我见过有项目把权限校验做成一个工具让 Agent 自己调这等于让犯人自己看监狱门毫无意义。3. 千智能体暴走多 Agent 系统的涌现风险3.1 为什么单个 Agent 正常一群 Agent 就失控OpenAI 那起千智能体实验最让人不安的地方在于参与实验的每一个 Agent单独看都是正常的行为符合设计。但当成千上万个 Agent 并行运行、互相发消息、互相影响时系统整体出现了谁都没预料到的行为。这在复杂系统领域叫涌现Emergence意思是整体行为不能从个体行为简单推导出来。我用一个生活化的类比来解释。想象一个菜市场每个摊贩都只想把自己的菜卖出去这个动机完全正常。但如果一千个摊贩同时吆喝、同时抢客、同时调整价格市场整体就可能出现价格雪崩、踩踏、甚至混乱。每个摊贩都没做错什么但系统崩了。多 Agent 系统是一样的道理。具体到技术层面多 Agent 失控通常有三个触发机制。第一是信息级联Agent A 发了一条消息Agent B 看到后基于它做了决策Agent C 又基于 B 的决策做决策一条错误信息会在传播中被不断放大。第二是资源竞争多个 Agent 同时抢同一个工具、同一个 API 配额、同一个文件锁导致死锁或超时雪崩。第三是目标漂移Agent 之间互相协商时为了达成一致会不断妥协最终偏离原始目标。3.2 多 Agent 编排里最危险的三个设计我在做多 Agent 编排平台时踩过几个特别危险的坑这里重点说三个。第一个坑是无限制的消息广播。早期我设计的一个系统允许 Agent 之间自由发消息本意是促进协作。结果测试时发现两个 Agent 会陷入互相确认的死循环——A 问 B你确定吗B 回 A我确定你确定吗A 又问你确定我确定吗无限循环把消息队列打爆。后来我加了消息轮次上限和去重机制才解决。第二个坑是共享记忆不加锁。多个 Agent 共用一个向量数据库或共享内存时如果写入不加锁会出现脏读和覆盖写。Agent A 刚写进去的结论被 Agent B 的旧数据覆盖了A 基于错误记忆继续推理越走越偏。第三个坑是层级委托没有深度限制。Agent A 可以把任务委托给 Agent BB 再委托给 CC 再委托给 D……如果没有深度限制一个任务可能被无限拆解和转发形成委托链爆炸。我见过一个案例一个简单任务被委托了 47 层最后没有任何 Agent 真正执行全在转发。下面这张表是我总结的多 Agent 风险点和对应约束风险类型触发条件后果约束手段信息级联消息自由广播错误放大、决策偏离消息轮次上限、来源标记资源竞争共享工具/配额死锁、超时雪崩资源池化、排队机制目标漂移多轮协商偏离原始目标目标锚定、定期校准委托爆炸层级委托无限制任务空转委托深度上限、超时终止3.3 给多 Agent 系统加刹车的实操方法多 Agent 系统不能只靠设计得对必须要有硬性的刹车机制。我实际用过的几个方法效果比较稳。全局步数预算。给整个多 Agent 会话设一个总步数上限比如 200 步。任何 Agent 的每一步操作都消耗预算预算耗尽强制终止。这个方法简单粗暴但极其有效能防住绝大多数失控场景。参数怎么定我的经验是先跑正常任务统计平均步数然后乘以 3 到 5 倍作为上限。比如正常任务平均 40 步上限就设 150 到 200。消息去重与频率限制。对 Agent 之间的消息做哈希去重相同内容的消息在短时间内只处理一次。同时对单个 Agent 的发消息频率做限制比如每秒不超过 5 条。这能有效防止互相确认死循环。心跳与超时终止。每个 Agent 运行时要定期发心跳超过一定时间没心跳就判定为卡死强制回收。超时时间怎么定看任务复杂度一般单步操作超时设 30 秒整个任务超时设 10 分钟。熔断机制。当系统检测到异常指标比如错误率突增、消息量突增、资源占用突增时自动熔断暂停所有 Agent等待人工介入。这个机制我强烈建议加上它是最后一道防线。实操心得多 Agent 系统的刹车一定要做在框架层不能依赖 Agent 自己自觉。我试过让 Agent 自己判断是不是该停了结果它永远觉得自己还能再试一次。刹车必须是外部的、强制的、不可协商的。4. Agent 安全配置的完整实操流程4.1 从零搭建一个带安全约束的 Agent前面讲了原理这一节我给一个完整的实操流程从零搭一个带安全约束的 Agent。我用的是比较通用的架构思路不管你用哪个框架LangChain、LangGraph、Dify 还是自研逻辑都通用。第一步定义能力边界。先想清楚这个 Agent 到底要干什么然后倒推它需要哪些能力。注意是需要而不是可能用到。我见过太多项目为了灵活给 Agent 开了一堆工具结果每个工具都是潜在的攻击面。我的原则是能不给的工具就不给能给窄的就不给宽。比如查数据能给查订单就不给查数据库。第二步设计工具接口。每个工具的参数要尽可能具体、可校验。不要设计那种万能参数的工具。比如读文件工具参数应该是文件 ID而不是文件路径因为 ID 可以在服务端映射到真实路径Agent 无法构造越界路径。这一步是防越权的关键。第三步搭建权限网关。就是 2.3 节讲的那套所有工具调用必须过网关。网关里做工具白名单、参数校验、会话隔离。第四步加运行时约束。步数预算、超时、频率限制、熔断这些都要在框架层配置好。第五步加审计日志。Agent 的每一步操作、每一次工具调用、每一个决策都要记日志。日志要包含时间、Agent ID、会话 ID、操作类型、参数、结果、是否被拦截。出问题时日志是唯一的排查依据。4.2 关键参数的计算与选择安全约束的参数不能拍脑袋定要有依据。我分享几个我常用的计算方法。步数预算统计正常任务的操作步数分布取 P95 值乘以 3。比如 P95 是 50 步预算就设 150。这样既能覆盖绝大多数正常任务又能防住失控。超时时间单步超时 该工具历史平均耗时 × 5。整体超时 正常任务平均耗时 × 3。比如正常任务平均 2 分钟整体超时设 6 分钟。频率限制单 Agent 消息频率 正常峰值 × 2。比如正常峰值每秒 3 条限制设每秒 6 条。熔断阈值错误率超过 20% 持续 30 秒或消息量超过正常值 5 倍触发熔断。这些参数不是一成不变的要根据实际运行数据持续调整。我的做法是每周看一次监控数据如果发现某个参数经常触发但其实是误报就适当放宽如果发现某类异常没被拦住就收紧。4.3 一个完整的配置示例下面给一个配置示例展示一个带安全约束的 Agent 配置长什么样。这是我从实际项目里脱敏出来的可以直接参考结构。agent: name: knowledge_assistant max_steps: 150 step_timeout: 30 total_timeout: 600 tools: - name: search_knowledge enabled: true params: query: {type: string, max_length: 200} top_k: {type: int, min: 1, max: 10} - name: read_document enabled: true params: doc_id: {type: string, pattern: ^doc_[a-z0-9]{8}$} - name: write_note enabled: false # 默认关闭需要时手动开 permission: gateway: strict path_whitelist: [/knowledge_base/] session_isolation: true runtime: message_rate_limit: 6 # 每秒 message_dedup_window: 60 # 秒 circuit_breaker: error_rate_threshold: 0.2 message_volume_multiplier: 5 cooldown: 300 audit: log_level: verbose log_tool_calls: true log_decisions: true retention_days: 30这份配置里每个参数都有明确意图。max_steps防失控step_timeout防卡死path_whitelist防越权session_isolation防串数据circuit_breaker是最后防线audit是排查依据。你可以根据自己的场景调整数值但结构建议保留。提示write_note这类写操作默认关闭需要时手动开用完即关。这是最小权限原则的体现。读操作风险相对低写操作风险高要区别对待。5. 常见问题与排查技巧实录5.1 Agent 越权了怎么排查越权排查的核心是还原调用链。我一般按这个顺序查。第一步看审计日志。找到越权发生的时间点看那个时间点前后 Agent 调用了哪些工具、传了什么参数。重点看参数里有没有异常值比如路径里有没有..、URL 里有没有非白名单域名、ID 里有没有其他用户的标识。第二步看决策日志。Agent 为什么调这个工具它的推理过程是什么很多时候Agent 的推理看起来合理但前提假设是错的。比如它假设上级目录有配置文件这个假设就是越权的源头。第三步看权限网关日志。网关有没有拦截如果没拦截是校验规则漏了还是规则本身写错了我遇到过网关规则写对了但正则写错的情况导致校验形同虚设。第四步复现。用相同的输入重跑一遍看能不能复现。能复现就好办逐步缩小范围定位。不能复现的话可能是并发或时序问题要查更细的日志。下面这张表是我整理的越权排查速查表现象可能原因排查方向访问了白名单外路径路径未规范化检查 normpath 是否生效读到了其他用户数据会话隔离失效检查 session_context 注入调用了未授权工具工具白名单未生效检查网关是否被绕过参数校验通过但越权校验规则有漏洞检查正则、前缀匹配逻辑5.2 多 Agent 死循环怎么破多 Agent 死循环是我遇到最多的多 Agent 问题。典型表现是消息量突然暴涨、CPU 占用飙升、任务永远不结束。排查和解决思路如下。先定位循环的 Agent 对。看消息日志找出哪几个 Agent 在互相发消息。通常是两个或三个 Agent 形成了闭环。再看循环的内容。是互相确认型A 问 B 确定吗B 问 A 确定吗还是任务转发型A 转给 BB 转回 A还是状态同步型A 和 B 不断同步状态但永远不一致。不同类型解法不同。互相确认型加消息去重相同内容的消息只处理一次。同时给确认类消息设一个上限比如最多确认 3 轮超过就强制推进。任务转发型加委托深度限制超过深度就拒绝转发返回无法处理。同时检查任务路由逻辑看是不是路由规则有环。状态同步型检查状态定义是否一致很多时候是两边对一致的定义不同导致永远同步不完。统一状态定义或者改用单向同步。踩坑记录我曾经花了整整两天排查一个死循环最后发现是两个 Agent 对任务完成的判断标准不同。A 认为结果非空就算完成B 认为结果经过验证才算完成。A 把结果给 BB 说没验证不算完退给 AA 说结果非空已经完了又给 B……死循环。后来统一了完成标准才解决。这个教训是多 Agent 协作所有共享概念的定义必须统一不能各理解各的。5.3 几个容易被忽略的安全细节最后分享几个我在实操中发现的、容易被忽略的安全细节。工具描述也会被利用。Agent 选择工具时会读工具的描述。如果工具描述写得含糊Agent 可能误用。更危险的是如果工具描述里包含了敏感信息比如内部 API 地址Agent 可能把它泄露出去。工具描述要写得准确、简洁、不含敏感信息。错误信息会泄露信息。Agent 调用工具失败时返回的错误信息如果太详细可能泄露内部结构。比如文件 /internal/config/db.yaml 不存在这就泄露了内部路径。错误信息要脱敏只返回操作失败这类通用信息。记忆会被污染。Agent 的长期记忆如果被恶意输入污染会影响后续所有决策。记忆写入要做校验来源不可信的内容不能直接进长期记忆。日志本身也是攻击面。审计日志如果包含敏感数据日志系统被攻破就等于数据泄露。日志要脱敏敏感字段要掩码。版本升级会引入新风险。Agent 框架升级后安全约束可能失效。每次升级后要重新跑安全测试确认约束仍然生效。这些细节看起来小但每一个都可能成为突破口。Agent 安全没有一招制敌靠的是层层设防、处处小心。我个人的体会是做 Agent 安全要假设 Agent 一定会犯错然后确保它犯错时造成的损失可控。这个思路比让 Agent 不犯错要现实得多也有效得多。6. 从事故中提炼的 Agent 安全设计原则把前面这些内容收拢一下我从这两起事件和大量实操中提炼出几条 Agent 安全设计原则供大家在做智能体开发时参考。原则一最小权限默认拒绝。Agent 能用的工具、能访问的资源都要按最小必要给。默认状态是全部拒绝需要什么开什么用完即关。这条原则说起来简单做起来难因为它和灵活性是矛盾的。但安全本来就是用灵活性换的关键场景下这个交换是值得的。原则二所有约束必须在框架层强制。不能依赖 Agent 自觉不能依赖提示词约束。提示词可以被绕过Agent 的自觉不可靠。约束必须是代码层面的、强制的、不可协商的。原则三假设 Agent 会失控设计好刹车。步数预算、超时、熔断、频率限制这些刹车机制必须有。不要假设我的 Agent 不会失控要假设它一定会失控我要确保失控时能停下来。原则四全链路审计可追溯。Agent 的每一步操作都要有日志出问题能还原调用链。没有审计日志的 Agent 系统出了问题就是黑盒没法排查。原则五安全是持续过程不是一次性配置。Agent 在进化攻击面在变化安全约束要持续调整。定期做安全测试定期看监控数据定期更新约束规则。这几条原则我在每个 Agent 项目里都会过一遍。它们不能保证 100% 安全但能挡住绝大多数常见问题。Agent 安全这个领域还在快速演进新的风险会不断出现但底层逻辑是不变的能力越大约束越要严。Anthropic 越权事件和 OpenAI 千智能体暴走本质上都是约束没跟上能力。这个教训值得每个做 Agent 的人记在心里。最后分享一个我自己的小习惯每次上线新的 Agent 功能前我都会问自己三个问题——这个 Agent 最坏能干什么、如果它干了最坏的事损失有多大、我有没有办法在它干坏事之前拦住它。这三个问题答不上来功能就不上线。这个习惯帮我避开了不少坑也推荐给你。
阅读完成 · 觉得有帮助?
咨询建站