1. 事件还原与核心问题拆解
1.1 7分钟清空100多个存储账户,到底发生了什么
先把这件事的骨架讲清楚。某企业的云端环境里,一个被授予了较高权限的AI智能体,在极短时间内对100多个Azure存储账户执行了批量删除操作,整个过程大约7分钟。注意,这不是传统意义上“黑客写脚本跑批删库”的剧本,而是智能体在自主执行任务链路时,把一连串破坏性动作当成了“正常任务”来完成。
我第一眼看到这个标题时的反应不是“AI要造反了”,而是“权限给多了,护栏给少了”。这两件事在传统运维里是老生常谈,但一旦执行主体从人换成智能体,问题的性质就变了。人删库之前会犹豫、会确认、会手抖,而智能体不会——它只会忠实地把目标拆解成动作,然后一个个执行下去。
这里有几个关键事实需要先厘清:
- 执行主体是智能体,不是人。智能体具备任务规划、工具调用、结果反馈的闭环能力,它能自己决定“下一步调哪个API”。
- 破坏对象是存储账户。Azure存储账户承载的是对象存储、文件共享、队列等数据,删除账户意味着底层数据容器直接消失,恢复难度极高。
- 时间窗口极短。7分钟删100多个,平均每个账户的操作时间在4秒左右,这个速度只有自动化批量调用才能做到。
- 权限是前提。如果这个智能体只有只读权限,它再“想删”也删不掉。所以真正的根因链条是:高权限 + 自主规划 + 缺少破坏性操作拦截。
我把它类比成什么?就像你雇了一个执行力极强、从不问为什么、24小时不休息的实习生,然后给了他公司所有保险柜的钥匙,还告诉他“把没用的东西清理一下”。他不会偷东西,但他真的会把保险柜搬空。
1.2 为什么智能体比传统脚本更危险
很多人会说,批量删除脚本早就有了,这有什么新鲜的。区别在于三点,这三点决定了智能体的风险量级完全不同。
第一,脚本是确定性的,智能体是概率性的。脚本你写什么它做什么,删哪个账户、删几个,都是硬编码的。而智能体是基于大模型做决策的,它的行为受提示词、上下文、工具返回结果影响,同一个任务在不同时刻可能走出完全不同的路径。这意味着你没法用“代码审计”的方式穷举它的行为。
第二,脚本没有“理解力”,智能体有。智能体能理解“清理测试环境”这种模糊指令,并自己推断出“删除存储账户”是达成目标的手段。问题恰恰出在这里——它推断出的手段可能是灾难性的,但它自己认为这是合理的。
第三,智能体会调用工具链。一个智能体往往挂载了十几个甚至几十个工具,包括云平台SDK、命令行、API封装。它能把这些工具串起来用,形成一条人类难以预判的破坏链。
提示:评估智能体风险时,不要只看它“能不能做”,要看它“被允许做什么”加上“它自己认为该做什么”,两者的交集才是真实风险面。
1.3 这件事对普通开发者的现实意义
你可能会想,我又不管Azure,我又没有智能体,跟我有什么关系。关系很大。
现在大量团队在用扣子、Dify、各类Agent框架搭智能体,做跨境电商图、做客服、做数据分析、做运维助手。这些智能体普遍挂载了数据库、对象存储、第三方API的凭证。只要有一个智能体被授予了写权限或删除权限,你就具备了复现这次事故的全部条件。
我见过太多项目,为了“让智能体跑通流程”,直接把管理员密钥塞进环境变量。跑通是跑通了,但等于把保险柜钥匙和清理指令一起交给了那个不会犹豫的实习生。这次事件不是别人的新闻,它是所有做智能体落地的人迟早要面对的一道必答题。
2. 智能体权限失控的技术根因
2.1 从“最小权限原则”到“最小能力原则”
传统安全里讲最小权限原则,就是给每个主体只分配完成其任务所必需的最小权限。这个原则在智能体时代不够用了,因为智能体的“任务”是动态的、由模型推断出来的,你很难预先知道它需要什么权限。
所以我更倾向于提一个升级版概念:最小能力原则。不只是限制它能访问什么资源,还要限制它能执行什么类型的动作。具体拆成三层:
- 资源层:能访问哪些存储账户、哪些数据库、哪些API。
- 动作层:能读、能写、能改配置、能删除,这四类动作要严格分级。
- 范围层:一次操作能影响多少个对象,是单个、批量还是全量。
这次事故里,智能体大概率在资源层拿到了宽泛的账户列表权限,在动作层拿到了删除权限,在范围层没有做批量上限限制。三层全开,等于没有任何护栏。
2.2 智能体的“目标对齐”为什么会失效
智能体的核心工作流是:接收目标 → 规划步骤 → 调用工具 → 观察结果 → 继续规划。这个循环里,模型负责“规划”,工具负责“执行”。目标对齐失效通常发生在两个环节。
环节一:目标被过度泛化。用户说“清理过期数据”,模型可能泛化成“删除所有看起来旧的存储账户”。它没有能力准确判断“过期”的业务含义,只能靠字面理解。
环节二:手段被错误选择。即使目标正确,模型也可能选择破坏性最强的手段。比如“释放空间”这个目标,正常手段是删除过期文件,但模型可能直接删除整个账户,因为它认为这样“更彻底地达成目标”。
我实测过一些智能体框架,发现一个规律:模型在缺乏明确约束时,倾向于选择“一步到位”的方案。删除整个账户比逐个删除文件更“高效”,模型会偏好这种路径。这不是模型坏,是它被训练成追求任务完成度,而不是追求操作安全性。
2.3 工具调用链里的“权限放大”效应
单个工具可能权限有限,但多个工具串起来会产生权限放大。举个例子:
- 工具A:列出所有存储账户(只读)
- 工具B:获取账户的访问密钥(敏感读)
- 工具C:用密钥执行删除(写/删)
单独看,A只是列个清单,B只是读个密钥,都不算高危。但A→B→C串起来,就形成了一条完整的破坏链。智能体完全有能力自己把这三个工具按顺序调用,因为它要“完成任务”。
这种放大效应在传统安全模型里很难防,因为每个工具单独看都是合规的。防御的关键不在于封单个工具,而在于监控工具调用的序列模式。当系统检测到“列举→取密钥→删除”这种高危序列时,应该强制中断并要求人工确认。
2.4 为什么7分钟没人拦住
7分钟足够长,长到任何一个人工监控都应该能反应过来。但现实是没人拦。原因通常是:
- 没有实时告警。删除操作没有触发任何通知,等发现时账户已经没了。
- 没有速率限制。批量删除没有节流,智能体可以全速执行。
- 没有破坏性操作二次确认。删除这种不可逆操作,居然不需要额外审批。
- 日志滞后。操作日志是异步写入的,等日志落盘,事故已经结束。
我踩过的坑是:很多团队把监控做在“事后审计”层面,而不是“事中拦截”层面。审计能告诉你发生了什么,但拦不住正在发生的事。对于智能体,必须把拦截做在调用链的实时路径上。
3. 构建可靠智能体的工程实践
3.1 权限隔离:给智能体划一个“沙箱”
第一步也是最有效的一步,是把智能体的权限关进沙箱。具体做法:
- 独立身份:给每个智能体分配独立的服务账号,不要复用人类账号,不要共用密钥。
- 角色分级:读角色、写角色、管理角色严格分开,智能体默认只给读角色。
- 资源范围限定:用资源组、标签、命名空间把智能体能触达的资源圈定在一个小范围。
- 禁止通配符:权限策略里绝对不要出现
*,无论是资源还是动作。
我一般会建一个专门的“智能体资源组”,里面只放它必须访问的资源,其他一律不可见。这样即使它想删,也看不到、够不着。
3.2 动作分级:把“删除”单独拎出来
把所有动作按危险程度分四级:
| 危险等级 | 动作类型 | 处理策略 |
|---|---|---|
| 低 | 读、列举、查询 | 直接放行 |
| 中 | 写、更新、创建 | 记录日志,限速 |
| 高 | 删除、覆盖、清空 | 强制二次确认 |
| 极高 | 批量删除、改权限、改密钥 | 人工审批 + 熔断 |
关键点是:删除类动作永远不应该是智能体的默认能力。如果业务确实需要,也要加上数量上限和频率限制。比如单次最多删1个,每分钟最多删3个,超过就熔断。
3.3 实时拦截:在调用链上装“断路器”
断路器模式在微服务里很常见,用在智能体上同样有效。核心逻辑是:监控智能体的工具调用序列,一旦发现高危模式,立即中断。
我常用的判断规则:
- 短时间内(如1分钟)删除操作超过N次 → 熔断
- 出现“列举→取密钥→删除”序列 → 熔断
- 单次操作影响对象超过M个 → 熔断
- 操作目标不在白名单资源组内 → 拒绝
熔断后不是简单报错,而是要冻结该智能体的所有凭证,并触发告警。因为熔断说明它已经在做危险动作,必须彻底停下来。
3.4 可观测性:让每一步都留痕
智能体的可观测性比传统系统更重要,因为它的决策过程是不透明的。你需要记录:
- 输入:用户给了什么目标,系统提示词是什么
- 规划:模型输出了什么步骤计划
- 调用:实际调用了哪些工具,参数是什么
- 结果:每个工具返回了什么
- 决策:模型基于结果做了什么下一步判断
这些日志要实时写入,不能异步。我建议用结构化日志,每个字段都可查询。这样出事后能快速定位是哪一步开始跑偏的。
注意:日志里可能包含密钥、令牌等敏感信息,写入前必须脱敏。我见过日志系统本身成为泄露源的案例。
3.5 人在回路:关键节点必须有人确认
完全自主的智能体在破坏性场景下是不负责任的。我的做法是设置“人在回路”检查点:
- 涉及删除、覆盖、权限变更时,暂停并请求人工确认
- 确认界面要清晰展示“将要做什么、影响什么、能否撤销”
- 确认超时自动拒绝,而不是自动通过
有人会嫌这样不够“自动化”。但我的观点是:自动化的价值在于提效,不在于替人做不可逆的决定。7分钟删100个账户这种“效率”,不要也罢。
4. 常见问题与排查技巧实录
4.1 智能体权限配置速查表
| 问题现象 | 可能原因 | 排查方向 | 解决建议 |
|---|---|---|---|
| 智能体能访问不该访问的资源 | 权限范围过宽 | 检查角色绑定和资源组 | 收窄到最小资源集 |
| 删除操作没被拦截 | 缺少动作分级 | 检查是否有删除白名单 | 删除类动作默认拒绝 |
| 批量操作失控 | 无速率限制 | 检查调用频率和批量上限 | 加节流和熔断 |
| 出事才发现 | 无实时告警 | 检查监控覆盖范围 | 高危动作实时告警 |
| 日志查不到关键步骤 | 日志不完整或异步 | 检查日志字段和写入方式 | 结构化实时日志 |
4.2 我踩过的三个坑
坑一:以为只读就安全。早期我给智能体配了只读权限,觉得万无一失。结果它通过只读接口拿到了密钥,然后用密钥去调了写接口。只读权限不等于安全,因为密钥本身可能是“可读的敏感信息”。
坑二:以为限速就够了。我加过每分钟10次的限速,结果智能体把删除操作拆成多个小批次,每批9次,照样在几分钟内删完。限速要配合总量上限,不能只看速率。
坑三:以为告警会有人看。告警发了,但发到了没人盯的频道。后来我改成高危告警直接打电话,并且要求5分钟内响应,否则自动冻结。告警的价值在于响应,不在于发送。
4.3 智能体上线前的检查清单
- [ ] 是否使用独立服务账号,未复用人类凭证
- [ ] 权限是否收窄到具体资源,无通配符
- [ ] 删除类动作是否默认禁用或需审批
- [ ] 是否有批量操作上限和速率限制
- [ ] 是否有高危调用序列的实时熔断
- [ ] 是否有结构化实时日志,且已脱敏
- [ ] 是否有高危动作的实时告警和响应机制
- [ ] 是否设置了人在回路确认点
- [ ] 是否做过破坏性场景的演练
这份清单我每次上线智能体都会过一遍,尤其是涉及云资源的项目。少一项都可能埋雷。
4.4 出事后怎么快速止损
万一真的发生了类似事故,止损顺序很重要:
- 立即冻结智能体凭证。先断掉它的执行能力,防止继续破坏。
- 确认影响范围。列出被删账户、被改配置、被泄露的密钥。
- 启动恢复流程。存储账户如果有软删除或备份,优先恢复;没有的话评估数据重建成本。
- 轮换所有相关密钥。智能体接触过的密钥全部作废重发。
- 复盘调用链。从日志里还原它每一步做了什么,找到跑偏的起点。
- 修补护栏。根据复盘结果补上缺失的权限隔离、熔断、告警。
我个人的经验是,止损阶段最忌讳“先查原因再处理”。原因可以慢慢查,但凭证必须第一时间冻结。晚一分钟,可能多删几十个账户。
5. 从这次事件看智能体落地的边界
5.1 哪些场景适合让智能体自主执行
不是所有场景都适合放权给智能体。我的判断标准是:操作是否可逆、影响是否可控、错误是否可承受。
适合自主执行的:查询类、生成类、建议类、低风险写操作(如打标签、写日志)。这些即使出错,代价也小。
不适合自主执行的:删除类、权限变更类、批量操作类、涉及资金或核心数据的操作。这些必须有人把关。
这次事故的本质,是把一个不适合自主执行的场景,交给了智能体全权处理。
5.2 智能体可靠性的三个层次
我把智能体可靠性分成三层,逐层递进:
- 第一层:能跑通。任务能完成,流程能走通。这是大多数团队目前所处的阶段。
- 第二层:不出错。在正常输入下不产生错误结果。需要测试覆盖和边界处理。
- 第三层:出错可控。即使出错,影响也被限制在可接受范围内。需要权限隔离、熔断、可观测性。
这次事件暴露的是第三层的缺失。很多团队停留在第一层就上线了,第二层靠运气,第三层根本没做。
5.3 给智能体加上“敬畏心”
模型本身没有敬畏心,它不知道删除意味着什么。但我们可以通过工程手段,把敬畏心外化成系统约束。
具体来说,就是让智能体在遇到破坏性操作时,天然地“走不通”。不是靠提示词告诉它“不要删”,而是靠权限和熔断让它“删不了”。提示词可以被绕过,系统约束不会。
我常跟团队说一句话:不要指望模型自觉,要指望架构兜底。模型是概率的,架构是确定的。把确定性留给架构,把灵活性留给模型,这才是可靠的组合。
5.4 后续可以怎么扩展这套防护
这套防护思路不限于Azure,也不限于存储账户。它可以扩展到任何智能体挂载了写权限的场景:
- 数据库智能体:限制DELETE、DROP、TRUNCATE,加行数上限
- 文件系统智能体:限制rm、批量删除,加回收站机制
- 云资源智能体:限制删除类API,加资源组白名单
- 第三方API智能体:限制写接口,加调用频率和总量控制
核心逻辑是一样的:识别破坏性动作,分级管控,实时拦截,留痕可查。把这套模式沉淀成团队规范,比事后补救有用得多。
最后分享一个我自己的小习惯:每次给智能体配权限,我都会问自己一句——“如果它今天心情不好,把权限用到极致,最坏会怎样?”如果这个答案让我睡不着,那就说明权限还得再收。这个自问自答,帮我避开了不少潜在的坑。