多智能体系统跑起来之后,很多人第一反应是“给 Agent 套个沙箱就安全了”。这个想法在外围工具链里很常见,但实际工程里并不成立。沙箱(sandbox)解决的是运行环境隔离问题,权限模型(permission model)解决的是访问授权问题。两者有关系,但绝对不能划等号。这篇文章想把它拆开讲清楚:为什么沙箱不能替代权限模型、多智能体系统里只靠沙箱会踩哪些坑,以及一个更稳妥的权限设计大概长什么样。适合正在做多 Agent 平台、Agent 工具链,或者要把多个 Agent 接入企业内部系统的开发者阅读。核心就一句话:先分清边界,再谈安全。
1. 先厘清沙箱和权限模型的实际边界
1.1 沙箱解决的是“运行环境隔离”问题
沙箱的本质,是限制一个进程能接触到的系统资源。文件系统、网络、系统调用、环境变量、设备节点,都能通过沙箱做隔离。常见实现有容器、虚拟机、seccomp、Landlock、Windows Sandbox、Firejail,以及各类云函数运行时自带的隔离层。
它的核心目标是:当一个程序不可信、可能出错、可能被恶意输入劫持时,把它关在一个受限环境里,让它无法直接影响宿主机器。换句话说,沙箱回答的是“这个进程在哪里跑”的问题。
比如 Linux 下用容器跑 Agent,默认情况下容器内进程看到的是独立的文件系统、独立的网络命名空间。即使 Agent 内部执行rm -rf /,删除的也只是容器内的根目录,不会直接把宿主根目录清空。这就是沙箱的价值。
但我们要注意到,沙箱做的事情非常“底层”。它不关心你是谁,不关心你正在执行的任务是什么,也不关心你是否有权读取某个文件。只要文件被挂载进了沙箱,沙箱内的进程就能读取。只要网络策略允许出站,沙箱内的进程就能发起外连。
1.2 权限模型解决的是“谁能做什么”问题
权限模型回答的才是真正的授权问题:某个主体(Agent、用户、服务)对某个客体(文件、API、数据库、消息队列)能执行哪些操作(读、写、执行、删除、发送),以及在什么条件下可以执行。
权限模型的常见形态包括:
- ACL 访问控制列表:直接列出某个文件或资源允许哪些主体访问。
- RBAC 基于角色:把权限赋给角色,再把 Agent 或用户加入角色。
- ABAC 基于属性:根据主体属性、资源属性、环境条件动态判断。
- Capability 能力机制:把某项权限做成一个不可伪造的凭据,只有持有凭据才能执行。
这套机制比沙箱要“上层”得多。它不关心进程是否被隔离,它关心的是“即使进程正常运行,也不能越权操作”。
举个例子:一个数据分析 Agent 被允许读取销售汇总表,但没被允许读取员工工资表。即使它运行在非常开放的容器里,权限模型也应该在访问数据库时拒绝它。反过来,如果权限模型允许它读取工资表,那么沙箱再严密也拦不住“合理权限范围内的滥用”,只能尽量降低泄露后对宿主的影响。
1.3 为什么两者经常被混为一谈
我观察到,很多多 Agent 平台在设计初期会把“给 Agent 一个容器”和“给 Agent 授权”合并成一步。平台方觉得:Agent 在容器里跑,文件在容器里,网络从容器出去,这不就安全了吗?
实际上这里有一个隐藏假设:容器环境等于可信边界。一旦平台这样设计,就会导致一个典型问题——沙箱内所有凭证和权限都被打包进去,Agent 在沙箱里拥有完整执行权,没有任何策略层拦截。
在系统层面也能看到类似现象。比如 Windows 的 Elevated Sandbox 在创建子进程、重开可写对象时,如果权限继承关系处理不当,就会出现“管理员沙箱内无法正常打开子资源”的异常。这说明沙箱本身的权限继承、句柄传递、文件可写性,都是独立的工程问题,需要单独设计,而不是“进沙箱就一切都好”。
所以,正确的理解方式应该是:沙箱是执行环境的边界,权限模型是业务操作上的授权边界。两者是两道不同的门,少一道都会漏风。
2. 多智能体系统里,单独依赖沙箱会出哪些问题
2.1 沙箱隔离了宿主,但没隔离 Agent 之间的横向越权
如果一个系统只有一个 Agent,那么沙箱带来的隔离效果还比较直观。但多智能体系统的核心特征是有多个 Agent 协作,它们会共享任务队列、共享数据库、通过消息总线通信,甚至访问同一个外部队列。
这时候沙箱只能保证每个 Agent 进程不能直接读写宿主的文件系统,但无法解决一个 Agent 冒充另一个 Agent 调用接口的问题。比如 Agent A 拿到任务队列的一条消息后,伪造 Agent B 的 ID 去调用下游 API,下游 API 如果只校验“请求来源是否来自某个容器”,就会放行。
我见过不少团队为每个 Agent 起一个独立容器,但仍然把同一个数据库账号写死在所有容器里。结果就是:任何一个 Agent 被提示词注入劫持,都能直接拖库。这根本不是沙箱能解决的问题,而是身份与授权没有独立设计的问题。
2.2 沙箱内的文件和网络权限可能被过度授予
很多沙箱配置天生就是“宽松模式”。启动容器时直接把整个项目目录挂载进去,为了让 Agent 能访问代码仓库,就把仓库挂到/workspace;为了让 Agent 能访问所有数据库,就把连接串放进环境变量。
这样做的结果是:沙箱里的 Agent 能访问的东西,比它实际完成某个任务所需的东西多得多。沙箱变成了“一个装了很多权限的透明盒子”——进程被隔离了,但盒子里所有资源它都能用。
在实际调试时,我一般会先看容器挂载了哪些目录、网络策略是默认 allow 还是默认 deny。很多“Agent 数据泄露”问题,根因不是模型不够强,而是启动命令里挂了-v /data:/data这种全量挂载,以及环境变量里放了不必要的敏感凭据。
2.3 沙箱解决不了“被授权的 Agent 做了超出预期的事”
权限模型不止要回答“能不能访问”,还要回答“能做什么程度的操作”。一个被授权读取用户订单的 Agent,如果被任务目标诱导,尝试批量导出订单列表,这算不算越权?
如果在权限模型层面没有“单次读取”和“批量导出”的区别,那么 Agent 执行的是同一个 API:查询订单。沙箱不会拦截,网络策略可能也允许。真正应该拦的是:权限层对“批量导出”这个动作的额外校验,比如数量阈值提醒、导出对象白名单、二次审批。
注意,这里不是要讨论如何绕过限制,而是说明一个工程事实:授权要细到“操作语义”级别。否则“有权限的 Agent”自身就可能成为数据风险源。
2.4 一个最简单的示例:沙箱内 Agent 调用内部 API
我建议用这个思路检查自己的多 Agent 系统。假设:
- Agent 运行在容器 A,文件系统与宿主隔离。
- 容器 A 内的 Agent 获取到一个访问令牌。
- Agent 调用内部订单服务的 API。
- 订单服务校验令牌,返回结果。
这个链路里,容器 A 只负责“托管 Agent 进程”,真正决定 Agent 能不能读订单的是第 4 步的令牌校验。如果令牌的 scope 是read_all_orders,那么容器 A 是否被沙箱隔离就不重要了。重要的是:Agent 为什么持有这么高权限的令牌?令牌为什么没有绑定任务 ID?
所以,沙箱真正隔离的是“Agent 进程失控后对运行环境的影响”,而不是“Agent 对业务资源的越权访问”。
3. 多智能体场景下权限模型应该怎么设计
3.1 权限模型的基本元素
一个能支撑多 Agent 系统的权限模型,至少要包含五类元素:
| 元素 | 含义 | 示例 |
|---|---|---|
| 主体 | 谁在执行操作 | Agent ID、任务 ID、用户身份 |
| 客体 | 操作的对象 | 文件、数据库表、API、消息主题 |
| 操作 | 执行的动作 | 读、写、执行、调用、订阅、删除 |
| 条件 | 允许的环境约束 | 任务上下文、时间范围、来源 IP、数据标签 |
| 策略 | 判断规则集合 | 允许/拒绝规则、审批规则、配额规则 |
很多系统只做到了前三个,而把后两个完全忽略了。这就导致“这个 Agent 能读订单”和“这个 Agent 永远能在任何任务里读所有订单”被混为一个权限粒度的表达。
3.2 最小权限原则在 Agent 上的落地
最小权限原则听起来简单,落地起来容易变形。原因在于多 Agent 系统中,一个 Agent 往往会执行多种不同类型的子任务。如果按“Agent”这个静态主体分配权限,最后一定会走向“全都要”,因为设计者无法预测后续任务会用到什么权限。
更实际的做法是引入“任务级身份”。每次任务启动时,系统根据任务类型、输入数据标签、目标系统,动态生成一个临时的权限组合。任务结束之后,这个权限组合立刻失效。
我在实践中通常这样分步:
- 为每个 Agent 分配一个长期身份,用于注册、日志、审计。
- 为每次任务创建一个短期凭证或者携带任务 ID 的调用上下文。
- 真正访问资源时,使用任务级凭证,而不是 Agent 级凭证。
- 任务级凭证只在任务生命周期内有效,且 scope 缩到最小。
这样做的好处是:即使某个 Agent 在一次任务里被恶意提示词劫持,攻击面也被限制在这一次任务、这批数据、这些工具范围内,而不是整个 Agent 的权限范围。
3.3 基于角色的权限与基于能力的权限怎么选
在单机或者单体应用时代,RBAC 非常流行。管理员创建角色,角色绑定权限,Agent 归属角色。优点是管理清晰,缺点是粒度粗。
多 Agent 系统我更建议使用基于能力(Capability)或基于策略(Policy)的结合方式。每个 Agent 拿到一组明确的“工具票据”,每个工具票据绑定:
- 允许访问的资源范围
- 允许执行的参数范围
- 允许调用的次数限制
- 是否允许把票据转授给其他 Agent
这种方式更接近分布式系统的真实需求。多 Agent 之间如果要协作,A 可以把一个受限能力票据传给 B,B 只能在这个范围内继续执行。如果只依赖 RBAC,这个“转授”过程很难做边界控制。
3.4 任务级动态授权与上下文约束
动态授权的关键是让“条件”成为权限判断的一部分。例如:
- 客服 Agent 只能在任务状态为
customer_service时读取订单详情。 - 数据分析 Agent 只能读取数据标签为
public_agg的表,不能访问pii标签的表。 - 运维 Agent 只能修改目标环境为
staging的配置,生产环境需要二次审批。
这些约束放在权限模型里,比放在沙箱配置里更可靠。沙箱配置很难表达“这个 Agent 在什么业务语义下可以做什么”,权限模型和策略引擎可以。
实际接入时,我会先梳理一份“资源敏感级”清单。把系统里可能被 Agent 触达的资源分为公开、内部、敏感、高危四类,然后为每类资源定义允许的操作和条件。这个清单比先写代码更重要。
4. 沙箱和权限模型如何配合使用
4.1 隔离层与授权层分开建设
理想的多 Agent 安全架构应该分成两个独立组件:
- 隔离层:负责进程隔离、资源限制、网络白名单、文件系统只读/读写策略。
- 授权层:负责身份、scope、策略评估、操作审批、审计记录。
两者通过接口协作。典型请求链路是:
- Agent 进程发起一个工具调用。
- 请求先从沙箱环境出来,到达统一的权限网关。
- 权限网关根据 Agent ID、任务 ID、工具名、参数、资源标签做策略判断。
- 策略允许后,请求才会被转发到真实的内部 API。
- 内部 API 响应返回后,网关记录审计日志。
注意,这里的权限网关一定要部署在沙箱之外,不能把策略判断逻辑也放在 Agent 容器内。否则 Agent 一旦被劫持,可以直接绕过自己的判断逻辑。
4.2 在沙箱内也不能跳过权限校验
这里有一个很容易犯的错误:觉得沙箱内的文件已经被隔离了,所以沙箱内读取文件不需要再做文件级权限控制。
问题是隔离不等同于分类。如果两个任务共享同一个挂载目录,只是通过不同子目录区分,那么 Agent 完全可以通过路径遍历读取另一个子目录的内容。如果沙箱内的文件系统是 union mount 或者绑定挂载,权限继承关系也会变得非常微妙。
稳妥的做法是:
- 沙箱内文件系统只挂载当前任务需要的目录,并且设置为只读。
- 敏感文件通过临时受控目录注入,用完即删。
- 即使文件已经在沙箱内,程序读取时仍然通过一个文件访问代理做路径白名单校验。
你可以把这理解为“纵深防御”:沙箱是最外层围栏,沙箱内的文件访问控制是第三道门,权限模型的策略判断是第二道门,审计日志是第一道可追溯的摄像头。
4.3 审计日志与可追溯性
多智能体系统的审计日志和传统单体应用不一样。单体应用只需要记录用户操作,多智能体系统需要记录:
- 哪个 Agent 发起了操作
- 操作属于哪次任务
- 任务的指令来源是什么
- 调用了哪个工具、传入什么参数
- 返回结果是否被下一个 Agent 当作输入继续传递
- 授权策略是否命中、是否触发审批
如果没有这些信息,一旦出现数据异常或权限越界,很难定位是哪个 Agent、哪个节点、哪次任务导致的问题。很多系统的问题是“能查数据库,但查不清操作链路”,这比权限配置错误更致命。
4.4 从单 Agent 到多 Agent 的权限升级路径
如果第一个版本只有一个 Agent,可以直接给它一个相对固定的身份和权限。但是当系统扩展到多个 Agent 时,要立刻引入以下组件:
- Agent 注册表:记录每个 Agent 的身份、密钥、角色、能力范围、所属项目。
- 服务间调用凭证:Agent 之间不能直接通过内网 IP 互信,必须使用短期凭证。
- 任务上下文传递:调用链路上要带上 task_id、agent_id、request_id,方便权限判断和审计。
- 策略热更新:不需要重启所有 Agent,就能动态调整某个 Agent 的权限范围。
- 配额与熔断:限制单个 Agent 一段时间内的调用次数和数据读取量。
这个升级路径的核心思路是:不要让多 Agent 系统退化成“一堆容器里各跑一个全权限服务”。Agent 数量越多,身份和授权必须越明确。
5. 实践中的判断标准与排查思路
5.1 判断一个多 Agent 系统是否真的安全
我不建议只看“有没有用沙箱”或者“用了什么沙箱”来判断安全性。更实用的方式是检查:
- Agent 是否拥有独立身份?还是所有 Agent 共用一个后台服务账号?
- 调用内部 API 时,网关是否校验 scope?还是只校验 token 是不是有效?
- 沙箱网络出站是默认允许还是默认拒绝?
- 不同任务的敏感数据是否物理隔离?还是共用目录、共用数据库账号?
- 撤销某个 Agent 的权限后,它是否真的不能再访问?还是只是界面隐藏?
- 是否有完整的审计链路,能从一次 API 调用反查到 Agent、任务和指令来源?
如果这些问题里有超过两个答案不清晰,那这个系统的安全边界大概率是有漏洞的,而且漏洞不在沙箱,在授权设计。
5.2 常见误判和排查顺序
排查“Agent 访问了不该访问的数据”这个问题时,我习惯按以下顺序走,不对,这里应该写完整的排查顺序:
- 先看现象:是进程级逃逸,还是业务数据越权访问?这是两类完全不同的问题。
- 再看身份:Agent 当前持有哪些凭证?这个请求携带了哪个 Agent ID 和任务 ID?
- 再看授权策略:访问这个资源需要什么 scope?Agent 是否被授予了这个 scope?
- 再看网络:请求从沙箱出来时,网络策略是否允许访问目标服务?
- 再看沙箱挂载:目标数据是否被挂载进了沙箱文件系统?
- 最后看日志:审计系统里是否记录了这次访问,是否能完整回放?
很多人一遇到数据越权就急着加沙箱规则,这是错误方向。如果业务权限本身就没设计好,沙箱只能做成“把所有敏感数据从沙箱里拿掉”,这会导致 Agent 无法正常完成工作,最终只能重新挂载,又回到原样。
5.3 最小可复现验证方式
对于刚搭建好的多 Agent 系统,我建议用一个最小场景验证权限模型是否生效:
- 创建 Agent A,授予读取目录
/data/project_a的权限。 - 创建 Agent B,授予读取目录
/data/project_b的权限。 - 设计一个任务:Agent A 尝试读取
/data/project_b中的文件。 - 检查结果:如果 Agent A 能读到,说明权限校验有缺口;如果被拒绝,但日志没有记录,说明审计链路不完整。
这个验证看起来很简单,但能暴露出的问题非常多。常见结果有三种:
| 实验结果 | 可能原因 |
|---|---|
| Agent A 直接读到 B 文件 | 权限校验形同虚设,或者直接用共享服务账号 |
| Agent A 报错“无权限”但日志没记录 | 可能是文件系统权限控制,但审计链路没接上 |
| Agent A 被拒绝且日志完整 | 权限模型基本可用,可以继续深化策略 |
跑通这个最小验证之后,再扩展到 API 调用、数据库读取、工具调用、Agent 间协作。每扩展一层,都要重复验证一次。
6. 落地时的一些经验建议
6.1 学习阶段不要被“沙箱 = 安全”带偏
刚接触多 Agent 系统时,可以先找一个现成框架跑通 Agent 的启动和工具调用。但学习阶段要刻意区分:哪些安全能力来自沙箱,哪些来自框架的权限模型。很多框架默认允许 Agent 任意读取本地文件、任意调用注册过的工具,这不是沙箱的问题,而是权限模型没做约束。
我建议学习时做三件事:
- 先用小样例跑通一个 Agent 的容器化启动。
- 然后尝试在无沙箱环境下运行同一个 Agent,看它能不能访问宿主目录。
- 再对比有沙箱、有权限校验、有审计日志三种配置下的表现差异。
这样你才能直观理解“沙箱管哪一层,权限模型管哪一层”。单看文档很容易觉得都差不多,实际跑一遍就清楚了。
6.2 生产环境优先把审计和最小权限建起来
如果是要上生产,我建议不要一上来就追求“所有 Agent 全部容器化 + 最严格沙箱”。先把基础打稳:
- 每个 Agent 有独立身份和独立凭证。
- 所有工具调用和管理操作都走统一网关。
- 所有敏感资源的访问都有审计日志。
- 任务级权限从最小集合开始,缺了再加,不要一开始就给全量。
- 密钥通过外部密钥服务注入,不写进镜像和环境变量。
这些做完之后,再逐步引入更严的沙箱、更强的网络白名单、更细粒度的文件系统隔离。顺序反了会导致一个常见结果:沙箱很严,但 Agent 能力被限制太多,无法正常工作,最后团队为了跑通功能,又悄悄把沙箱放开。
6.3 给架构师和开发者的几个提醒
写代码之前,先画一张“资源-操作-主体”矩阵。把系统里所有会被 Agent 触达的资源列出来,标注允许的操作范围、敏感等级、是否需要审批。这张表是权限模型的初始输入,也是沙箱挂载和白名单策略的参考依据。
沙箱策略和权限策略要同步变更。很多项目在调试期为了快速联调,会临时放宽网络限制或者挂载额外目录。联调结束后又忘记收回。我建议把沙箱策略和权限策略都纳入版本管理,任何变更都走代码提交和评审,不能只靠某个人在服务器上临时改。
多 Agent 系统最常见的风险,不是某个 Agent 能力太强,而是所有 Agent 混在一起,权限边界模糊。越早引入 task_id、request_id、Agent ID 这类上下文标识,后期做权限收敛和问题排查越省力。如果等项目已经上线再补,基本上要重构一遍请求链路。
最后再重复一遍我一直坚持的判断:沙箱是隔离工具,权限模型是授权工具。隔离工具负责把影响范围控制在盒子里,授权工具负责判断盒子里的动作是否被允许。两者配合才是完整的边界设计。只靠沙箱的多智能体系统,不是安全,只是看起来像安全。