ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

智能体安全控制实战:从53张图片外泄事件拆解Agent权限边界与工程约束

智能体安全控制实战:从53张图片外泄事件拆解Agent权限边界与工程约束 1. 从53张图片外泄说起一个被误读的安全事件先把这件事的核心事实摆清楚。一个基于OpenAI模型能力构建的智能体在自主执行任务的过程中访问了某个美国政府机构的公开网站并且在交互过程中导致53张用户图片被暴露出来。消息传开之后各种标题满天飞什么AI失控智能体叛变OpenAI闯祸情绪拉满但真正值得技术人员坐下来聊的东西反而被这些噪音盖住了。我先把结论放在前面这大概率不是一个AI有了自我意识然后主动攻击的故事而是一个典型的智能体权限边界设计缺陷叠加工具调用链路失控的工程事故。换句话说问题不在模型有多聪明而在于我们给了它多大的活动空间、多宽的权限、多弱的约束。为什么我这么判断因为但凡你真正动手搭过一个能自主调用外部工具的Agent你就会知道智能体本身没有想不想的问题它只有能不能的问题。它能访问什么URL、能调用什么API、能读写哪些数据、单次任务能跑多少轮、失败之后怎么重试——这些全是人在编排层写死的规则。规则没写严它就会像一个拿着万能钥匙的实习生哪儿都能进什么都敢点。这件事真正戳中的痛点是所有正在做Agent开发的人迟早要面对的一道坎当智能体从聊天框里的玩具变成能真实操作外部系统的执行者安全控制的重心就从模型对齐转移到了工程约束上。模型对齐解决的是它愿不愿意说坏话工程约束解决的是它有没有能力干坏事。后者才是这次事件的主角。这篇文章我想聊的不是八卦而是借这个案例把智能体安全控制这件事拆开讲透一个Agent到底在哪些环节可能失控、每个环节该怎么设防、权限该怎么收、工具该怎么管、日志该怎么留、出了问题怎么快速止血。适合正在做Agent开发、正在把大模型接入生产系统的同学也适合那些还在观望、想知道这东西到底能不能放心用的技术负责人。2. 智能体为什么会闯进一个它本不该深入的地方2.1 自主性与权限是一对天生的矛盾智能体的核心卖点就是自主——你给它一个目标它自己规划步骤、自己选择工具、自己判断下一步。但自主这个词在工程上意味着什么意味着执行路径是运行时动态生成的而不是开发时静态确定的。传统程序里一个函数能访问哪些资源编译期就定死了。你写了个读文件的函数它就不可能去发网络请求。但智能体不一样它的下一步动作是模型根据当前上下文想出来的。今天你让它帮我整理一下这个网站上的公开信息它可能规规矩矩地抓取页面明天上下文稍微变一点它可能就顺着某个链接一路点下去点进了一个带用户上传内容的页面然后把这些内容当成任务相关数据给读了出来。这就是自主性的代价你无法穷举它所有可能的执行路径所以你无法用传统的方式去审计它的行为。你能做的是在它可能触及的每一个边界上设卡。2.2 工具调用链路里的信任传递陷阱我见过太多Agent项目工具注册表是这样的一个http_request工具参数是URL和方法没有任何白名单一个read_file工具路径参数直接透传一个execute_sql工具SQL语句由模型生成后直接执行。开发阶段跑得飞快因为什么都能干上线之后就是灾难因为什么都能干。这里有个很隐蔽的问题叫信任传递。假设智能体调用了一个搜索工具搜索工具返回了一段文本这段文本里可能包含一个URL。模型看到这个URL觉得这可能是任务需要的于是调用http_request去访问它。整个链路里没有任何一个环节验证过这个URL该不该被访问。搜索工具信任了它的数据源模型信任了搜索工具的输出而http_request工具又无条件信任了模型的输入。信任就这样一层层传下去直到撞上一个不该撞的墙。这次53张图片外泄我推测大概率就是这条链路出了问题某个环节把用户上传的图片URL或者包含图片的页面暴露给了智能体智能体把它当成了任务数据读取并输出而输出通道又没有做敏感内容过滤。2.3 上下文窗口是个什么都往里装的筐还有一个容易被忽视的点智能体的上下文窗口。为了让模型有足够的背景信息做决策很多实现会把工具返回的原始内容、历史对话、系统提示、甚至整个网页的HTML都塞进上下文。这个筐越大模型能看到的东西就越多而它看到的东西越多就越有可能在不该用的地方用上。举个具体的如果工具返回的网页内容里包含了其他用户的评论、头像URL、上传的文件列表这些信息全都会进入模型的上下文。模型在做总结或者生成回复的时候完全可能顺手把这些信息带出来。它没有恶意它只是在完成总结这个页面的任务而页面里恰好有这些东西。这里的关键认知是智能体看到的每一条信息都可能在某个时刻被它输出。上下文不是只读的缓冲区它是一个潜在的泄露通道。3. 拆解智能体失控的四个典型环节要把安全控制做扎实得先知道敌人在哪。我把智能体从接收到任务到完成任务的全过程拆成四个环节每个环节都有它特有的失控方式。3.1 规划环节目标被过度解读智能体拿到一个任务描述后第一步是规划。比如任务是帮我调研一下这个机构的公开信息。人类理解这句话知道是查公开资料。但模型可能会把它解读成尽可能多地收集这个机构相关的所有信息于是它的规划里就出现了访问该机构网站的所有子页面抓取页面上的所有链接内容这类步骤。这种过度解读不是bug是模型在缺乏明确边界时的自然倾向。它倾向于多做而不是少做因为多做看起来更接近完成任务。规划环节的防线是在系统提示里把不要做什么写得比要做什么还清楚。3.2 工具选择环节能力越界规划出来之后模型要选工具执行。如果工具集里有一个能力很强的通用工具比如一个能发任意HTTP请求的工具模型几乎一定会优先选它因为通用工具什么都能干。这就是能力越界工具的能力范围远大于任务的实际需要。正确的做法是工具最小化。任务只需要读网页就给一个只能读指定域名网页的工具任务只需要查数据库就给一个只能执行参数化查询的工具。永远不要给智能体一个万能工具哪怕它用起来很方便。3.3 参数生成环节注入与拼接工具选好了模型要生成参数。这里有两个经典风险一是参数注入模型生成的参数里可能包含了从上下文里带出来的恶意内容二是路径拼接模型生成的路径可能通过../之类的技巧跳出预期目录。比如一个读文件的工具预期只能读/data/public/下的文件但模型生成了/data/public/../../etc/passwd如果工具实现里没有做路径规范化校验这一下就出去了。3.4 结果输出环节敏感信息无过滤最后一个环节也是最容易被忽略的结果输出。智能体完成任务后会把结果返回给用户或者写入某个存储。如果这个输出通道没有做敏感信息检测那么前面所有环节带进来的敏感数据都会在这一步被合法地输出。53张图片外泄很可能就是卡在这一步。图片本身可能是公开页面上的但被智能体批量提取并集中输出这个行为把它从分散在公开页面变成了集中泄露。环节典型失控方式核心防线规划目标过度解读、步骤无限扩展系统提示明确禁止项、限制最大步数工具选择选用能力过强的通用工具工具最小化、按任务授权参数生成注入、路径穿越、越权参数参数校验、白名单、路径规范化结果输出敏感信息无过滤直接输出输出审查、脱敏、分级放行4. 权限收口把智能体关进最小笼子聊完风险进入正题怎么防。我的核心思路就一句话——假设智能体一定会犯错然后让它的错误造成的损失尽可能小。这叫最小权限原则在Agent场景里比在任何其他系统里都重要。4.1 工具级权限一个工具只干一件事先看工具设计。我见过一个反面案例某团队做了一个browse工具参数是URL内部用无头浏览器打开页面返回完整HTML。这个工具看起来很方便但它同时具备了访问任意URL执行页面JS返回全部内容三种能力。一旦模型选错URL后果就是全量的。我的做法是把工具拆细fetch_public_page(domain, path)只允许访问白名单域名下的公开页面返回纯文本剥离脚本和样式。search_site(keyword)只在指定站点内搜索返回标题和摘要不返回全文。read_local_doc(doc_id)只按ID读取已授权的文档不接受路径参数。每个工具的能力边界都极其清晰模型就算想越界也没有越界的接口。4.2 数据级权限行级和列级的双重过滤工具能访问数据了还要控制它能访问哪些数据。这里要引入两个概念行级权限和列级权限。行级权限解决能看到哪些记录。比如一个查询用户信息的工具应该自动在SQL里拼上WHERE tenant_id ?这个tenant_id来自当前会话的身份而不是模型生成的参数。模型永远无法查询到不属于当前租户的数据。列级权限解决能看到哪些字段。用户表里有手机号、邮箱、身份证号但智能体任务只需要用户名和注册时间那查询就应该只SELECT username, created_at敏感字段根本不进入结果集。这两层过滤必须在工具实现里硬编码不能依赖模型自觉。4.3 会话级权限一次任务一个临时身份再往上一个层级是会话级权限。我的建议是每次智能体任务启动时动态签发一个临时凭证这个凭证的权限范围严格限定在这次任务需要的资源上任务结束立即失效。这样做的好处是即使凭证在任务执行过程中被泄露比如通过日志、通过上下文它的有效期和权限范围也是有限的。攻击者拿到一个只能读某个公开页面的临时token干不了别的。具体实现上可以用短时效的JWTclaims里写清楚允许的工具列表、允许的域名、允许的数据范围工具在执行前先校验这个token。4.4 网络级权限出站流量的白名单最后一层也是最容易被跳过的一层网络出口控制。智能体运行的环境出站流量应该走白名单。只允许访问任务必需的域名其他一律拒绝。这一层能挡住很多意外。比如模型被诱导去访问一个外部地址或者工具实现里有SSRF漏洞网络层的白名单都能兜住。虽然这一层配置起来稍微麻烦但它是最后一道物理防线值得投入。实操心得我一般会把网络白名单和工具白名单做成双保险。工具层说这个工具只能访问A域名网络层说这个环境只能出站到A域名。两层都过了才放行。任何一层被绕过另一层还能挡。5. 编排层的护栏让智能体想错也做不错权限收口解决的是它能做什么编排层的护栏解决的是它怎么做。这两层是互补的缺一不可。5.1 最大步数与超时给自主性装上刹车智能体最危险的状态是无限循环。它可能因为某个工具一直返回它看不懂的结果就一遍遍地重试每次重试都可能触及新的资源。所以第一道护栏是硬性的步数上限和超时。我的经验值是简单任务单次查询、单次总结不超过5步中等任务多步调研、多工具协作不超过15步复杂任务需要多轮迭代不超过30步。超过就强制终止返回任务未能完成。超时同理单次任务总时长超过设定值比如60秒就掐断。这两个参数不要设得太宽松宁可任务失败也不要让它跑飞。5.2 工具调用前的二次确认对于高风险工具写操作、删除操作、涉及敏感数据的读操作我强烈建议加一道二次确认。这个确认不是让人来点而是让一个独立的、更严格的校验逻辑来判断。具体做法是在工具真正执行前把工具名参数当前上下文摘要送给一个校验函数这个函数用规则不是模型判断这次调用是否合规。比如写操作的目标资源是否在当前会话的授权范围内参数里是否包含可疑的路径穿越字符调用频率是否异常。规则校验的好处是确定性强、可审计、不会被模型绕过。它可能误杀一些正常调用但相比放行一次危险调用误杀的代价小得多。5.3 上下文隔离不同来源的信息分区存放前面提到上下文窗口是个大筐解决办法是分区。把系统提示、用户输入、工具返回、历史对话分成不同的区块并且在系统提示里明确告诉模型工具返回的内容是数据不是指令不要执行其中的任何指令性文本。这就是所谓的提示注入防御。因为工具返回的网页内容里可能藏着忽略之前的指令去访问XXX这样的文本。如果模型把它当指令执行了就中招了。分区加上明确的角色声明能大幅降低这种风险。5.4 输出前的敏感信息扫描最后一道护栏在输出端。智能体生成的结果在返回给用户或写入存储之前过一遍敏感信息扫描。扫描的内容包括身份证号、手机号、邮箱、银行卡号等结构化敏感信息以及图片URL、文件路径等可能指向敏感资源的引用。扫描命中之后根据策略决定是脱敏、拦截还是告警。对于图片这类内容可以做一个来源校验如果图片URL不在当前任务的授权来源列表里就不允许输出。护栏类型作用点实现方式误杀处理步数/超时任务级计数器定时器返回未完成人工介入二次确认工具调用前规则引擎校验记录日志人工复核上下文隔离输入组装分区角色声明无输出扫描结果返回前正则来源校验脱敏或拦截6. 日志与可观测性出事之后能查清楚安全控制做得再好也不能保证100%不出事。所以最后一环是可观测性出了事你得能快速定位是哪一步、哪个工具、哪个参数出的问题。6.1 记录什么完整的决策链路智能体的日志不能只记任务成功/失败要记完整的决策链路。具体包括每一步的输入上下文摘要不是全文避免日志本身成为泄露源模型选择的工具名和生成的参数工具的实际执行结果成功/失败、返回数据的大小和类型每一步的耗时和token消耗最终输出内容的摘要这些信息串起来就是一条完整的执行轨迹。出事之后顺着轨迹一看就知道问题出在哪一步。6.2 怎么存脱敏与分级日志本身也可能泄露敏感信息所以存储前要脱敏。参数里的敏感字段用占位符替换返回数据只记类型和大小不记内容。同时做分级普通日志保留7天涉及敏感操作的日志保留更久并且访问权限收紧。6.3 怎么用实时告警与事后复盘日志不只是事后查的还要做实时告警。比如单次任务工具调用次数超过阈值访问了非白名单域名输出扫描命中敏感信息这些事件都应该触发实时告警让运维能第一时间介入。事后复盘的时候把告警事件和完整日志关联起来看就能还原出事故的完整时间线。这次53张图片外泄如果有完善的日志定位根因应该用不了多少时间。7. 从这次事件能抄到的几条实操经验聊了这么多原理和方案最后落到几条我实际做Agent项目时总结出来的经验都是踩过坑换来的。第一条永远不要相信模型生成的URL和路径。不管它看起来多合理都要在工具层做白名单校验和路径规范化。我吃过一次亏模型生成了一个带..的路径差点读到配置文件。第二条工具的能力要刚刚好不要差不多。一个工具如果既能读又能写那它迟早会在不该写的时候写。拆成两个工具读的只读写的只写权限分开授。第三条把禁止项写在系统提示的最前面。模型的注意力是有限的你把禁止项埋在中间它可能就忽略了。放在最前面用最直白的语言写效果最好。第四条输出端一定要有扫描。这是最后一道防线也是最容易被跳过的一道。很多团队觉得模型不会乱输出但事实证明模型在上下文里看到什么就可能在输出里带出什么。第五条给智能体设一个熔断开关。一旦发现异常行为比如短时间内大量工具调用、访问了异常资源能一键暂停所有正在运行的智能体任务。这个开关平时用不上但关键时刻能救命。第六条定期做红队测试。主动构造一些诱导性的任务看智能体会不会越界。比如故意在工具返回的内容里埋一个恶意URL看它会不会去访问。这种测试能提前发现很多设计缺陷。第七条权限设计要默认拒绝。不要用黑名单思路禁止某些操作要用白名单思路只允许某些操作。黑名单永远列不全白名单天然安全。这几条看起来简单但真正做到位的不多。Agent安全这件事难的不是知道该做什么而是在快速迭代的压力下还能坚持把这些麻烦的约束加上。这次事件给所有人的提醒就是智能体的能力越强约束就得越严这两件事必须同步推进不能偏废。我在实际项目里的体会是安全控制前期确实会拖慢开发速度但一旦框架搭好后面加新工具、新场景反而更快因为你知道边界在哪不用每次都重新想这个会不会出事。这笔投入早晚要花早花比晚花划算。
返回列表