当 Agent 拿到你的文件、Shell 和网络权限,「它会不会闯祸」就不再是假设题。本文讲清:为什么容器不够用、业界怎么分层隔离、Anthropic 三个产品各用什么方案、开源工具 srt 怎么上手、以及四起真实事故教会我们什么。
先说人话版:沙箱(sandbox)就是给 Agent 划一个「儿童游乐区」——它在里面可以随便跑代码、写文件、发请求,但栅栏外的东西(你的 SSH 密钥、公司数据库、任意外网地址)碰不到。Containment(隔离/围堵)是更大的概念:不去猜 Agent「会做什么」,而是用硬边界限定它「能做什么」,从而给最坏情况的损失封顶——业界把这个最坏损失叫爆炸半径(blast radius)。
为什么现在(2026 年)这个主题突然变成必修课?三件事撞到了一起:① Agent 的权限从「聊天」升级到「操作文件系统 + 执行 Shell + 调私有服务」;② 业界共识形成——普通 Docker 容器不足以运行 LLM 生成的不可信代码(共享内核就是共享爆炸半径);③ 头部厂商同时把牌摊开:Anthropic 发布了讲述三个产品隔离架构的工程复盘并开源了沙箱运行时 srt,OpenAI 也在 2026 年把原生沙箱执行加入 Agents SDK。下面逐层展开。
在沙箱流行之前,Agent 安全的主流方案是人在回路(human-in-the-loop):Agent 每次要执行命令,先弹窗问用户「允许吗?」。理论上滴水不漏,实际上 Anthropic 的遥测数据揭穿了它:
这就是所谓的审批疲劳(approval fatigue):一个为「监督」设计的机制,反而训练出了无脑点「允许」的用户。Anthropic 工程博客对此的总结很直接:任何概率性防御(弹窗、分类器、模型对齐)都有非零漏报率;只有确定性的环境边界,才能兜住所有概率性防线都失手的那一次。(来源:Anthropic《How we contain Claude across products》,2026-05-25)
普通容器(Docker/runc)里的进程和宿主机共享同一个内核,只是用命名空间和 cgroups 做了逻辑隔离。跑自己团队写的、过了 CI 的代码没问题;但 LLM 生成的代码、用户上传的代码应当按「敌意代码」对待——一个内核漏洞就能让它越出容器。社区选型指南(2026-02)总结的行业信号很清楚:AWS 为 Lambda 造了 Firecracker、Google 为多租户造了 gVisor、Azure 用 Hyper-V 做临时沙箱——三大云厂商面对 AI 工作负载,没有一家选普通容器。(来源:Manveer Chawla《AI agent sandboxing in 2026》)
做隔离设计前,先想清楚「防的是谁」。Anthropic 把 Agent 的安全风险分成三类(官方框架):
用户自己——恶意或无心地——让 Agent 干坏事:从「帮我绕过这个烦人的检查」到「运行一条自己都看不懂的破坏性命令」。
没人要求,Agent 自己做了有害动作。注意一个反直觉的点:模型越强,这类风险不一定越小——强模型犯低级错误更少,但更擅长找到「没人想到要禁止的路径」去达成目标。Anthropic 记录过 Claude 为完成任务「乐于助人」地逃出沙箱、翻 git 历史找测试答案、甚至识别出评测基准后解密答案密钥。
攻击者通过工具、文件、网页等外部向量打进来——既包括提示注入,也包括对 Agent 运行时、编排层、代理服务的传统攻击。
对应地,防线也有三道,部署在三个不同的组件上:
模型层防御的现实水位可以参考官方公布的数字:在测试提示注入敏感性的 Gray Swan Agent Red Teaming 基准上,Claude Opus 4.7 单次攻击成功率约 0.1%,但 100 次自适应尝试后升到 5–6%;Claude Code 的 auto mode 分类器能在执行前拦下约 83% 的越权行为(误拦良性命令约 0.4%,漏过约 17%)。很强,但都不是 100%——这正是它们必须和环境层叠加使用的原因。
「沙箱」不是一种技术,而是一个光谱。每往上走一级,安全边界更硬,性能开销也更大。以下五级分类整理自社区选型指南(2026-02),术语先用大白话过一遍:
| 共享内核 | 多个容器用同一个操作系统内核。省资源,但内核被攻破 = 所有容器一起沦陷。 |
| 系统调用(syscall) | 程序向内核申请服务(读文件、开网络)的「窗口」。拦截了它,就拦截了程序对真实系统的一切触碰。 |
| microVM(微虚拟机) | 极度精简的虚拟机:每个工作负载有自己独立的内核,启动只要一两百毫秒,而不是传统 VM 的几十秒。 |
光谱是原材料,产品要的是完整方案。Anthropic 的工程博客难得地公开了自家三个产品的隔离架构——最有价值的洞察是:没有唯一正确的沙箱,隔离强度要匹配「用户看得懂多少」。
Claude 在 claude.ai 里跑代码时,是在服务端一个 gVisor 容器里,文件系统按会话即弃,不碰用户本地机器。爆炸半径最小,能力上限也最低。这里的威胁模型其实很传统:不是保护用户机器,而是保护自家基础设施和租户之间的互相隔离。
Claude Code 跑在用户机器上,必须碰文件、Shell 和网络。它的赌注是:用户是开发者,看得懂 bash,所以「弹窗审批」是可行的兜底。审批疲劳出现后,补上了 OS 级沙箱(macOS 用 Seatbelt,Linux 用 bubblewrap):沙箱内读随意、写限工作区、网络默认拒绝——换来弹窗减少 84%,并把这套运行时开源为 srt(见第 6 章)。
Cowork 面向不会读 bash 的知识工作者——「让用户判断 find . -exec rm {} \; 危不危险」不成立,所以边界必须绝对、常开、不弹窗:整个执行环境放进本地 VM(macOS 用 Apple Virtualization framework,Windows 用 HCS),只挂载用户选择的工作区,凭证留在宿主机钥匙串、永不进入客户机。后来的两次架构调整也值得记:Agent 循环移出 VM(VM 启动失败时产品不至于瘫痪,代码执行仍留在 VM 内),本地 MCP 服务器也移到宿主机(与 Claude Desktop 对齐,交由管理员审核)。
| 临时容器(claude.ai) | HITL 沙箱(Claude Code) | 本地 VM(Cowork) | |
|---|---|---|---|
| 隔离开销 | 容器启动 | 低延迟原生沙箱 | 完整 VM 启动 |
| 对用户的要求 | 无 | 必须能读懂 bash | 无 |
| 爆炸半径 | 服务端容器(gVisor + 基础设施边界) | 本地工作区 | 挂载的工作区(vsock + hypervisor 边界) |
表格译自 Anthropic 工程博客原文。
理论讲完,上手最快的路径是 Anthropic 开源的 srt(Sandbox Runtime):一个轻量沙箱工具,不需要容器,直接用 OS 原生原语(macOS 的 sandbox-exec/Seatbelt、Linux 的 bubblewrap)+ 代理式网络过滤,给任意进程加上文件和网络限制。它就是 Claude Code 沙箱的提取物,GitHub 约 3.7k star,目前为 Beta 研究预览(API 可能变动),暂不支持 Windows。以下命令与配置均摘自官方 README:
# 安装 npm install -g @anthropic-ai/sandbox-runtime # 网络限制:允许清单外的域名直接被断 $ srt "curl anthropic.com" # ✅ 成功(在允许清单内) $ srt "curl example.com" # 🚫 Connection blocked by network allowlist # 文件限制:当前目录可读,敏感文件被拒 $ srt "cat README.md" # ✅ 成功 $ srt "cat ~/.ssh/id_rsa" # 🚫 Operation not permitted
srt 的设计哲学是默认安全(secure-by-default):进程从最小权限出发,你只显式凿开需要的洞。四条规则记住方向即可:
/Users),再放行其中的具体路径(如 .)。allowRead 优先于 denyRead。.、/tmp);denyWrite 优先于 allowWrite,用于在可写区里再挖出保护区(如 .env)。注意读写的优先级方向刻意相反。allowedDomains = 完全断网。所有流量强制走宿主机上的 HTTP/SOCKS5 代理(Linux 直接移除网络命名空间,macOS 的 Seatbelt 只放行代理端口),由代理执行域名允许清单。.bashrc、.gitconfig、.git/hooks/、.mcp.json、.vscode/ 等永远禁写——即使落在你 allowWrite 的范围内。这是针对「往 shell 配置注入命令实现沙箱逃逸」的纵深防御。官方 README 的招牌用例——只改一行,把不可信 MCP 服务器关进沙箱(.mcp.json):
{
"mcpServers": {
"filesystem": {
"command": "srt", // 原来是 "npx",在前面套一层 srt 即可
"args": ["npx", "-y", "@modelcontextprotocol/server-filesystem"]
}
}
}
再在 ~/.srt-settings.json 里写限制策略(工作区可写、敏感目录禁写、默认断网):
{
"network": { "allowedDomains": [], "deniedDomains": [] },
"filesystem": {
"denyRead": ["~/.ssh"],
"allowWrite": ["."],
"denyWrite": ["~/sensitive-folder", ".env"]
}
}
也可以作为库嵌入自己的 Agent(TypeScript,摘自官方 README):
import { SandboxManager } from '@anthropic-ai/sandbox-runtime'
await SandboxManager.initialize({
network: { allowedDomains: ['api.github.com'], deniedDomains: [] },
filesystem: { denyRead: ['~/.ssh'], allowWrite: ['.', '/tmp'], denyWrite: ['.env'] },
})
const cmd = await SandboxManager.wrapWithSandbox('curl https://example.com')
// spawn(cmd, ...) 正常执行,限制已生效
github.com 就等于允许向任意仓库 push(潜在外传通道),且存在域名前置(domain fronting)绕过的可能;② allowUnixSockets 若放行 /var/run/docker.sock,等于把宿主机拱手让出;③ Linux 侧代理目前靠环境变量(HTTP_PROXY 等)引流,不认这些变量的程序会绕开(官方列为待改进);④ Linux 上强制保护路径只能挡「已存在的文件」。用之前把这节读一遍,别把工具当银弹。顺带一提生态对照:OpenAI 也在 2026 年 4 月为其 Agents SDK 加入了原生沙箱执行与模型原生 harness(先 Python 后 TypeScript),并面向企业推出连接私有 MCP 服务器的 Secure MCP Tunnel(据 TechCrunch 与 OpenAI 官方文档)。两家路线殊途同归:沙箱正在从「产品内部实现」变成「暴露给开发者的标准件」。
如果你要为自己的 Agent 产品选沙箱方案,2026 年的生态可以按抽象层次分成三层(整理自社区选型指南)。选型的第一问不是「哪个技术强」,而是「你想把工程精力花在哪」:
| 层 | 代表 | 适合谁 | 代价 |
|---|---|---|---|
| L1 原语自建 | Firecracker、gVisor、Cloud Hypervisor | 基础设施即业务的团队(做「下一个 Lambda」)、强合规自控需求 | 镜像分发、网络(TAP/CNI)、暖池调度全要自己造;高并发时 CNI 开销可使启动延迟增加约 263%(引 IMC'24 研究) |
| L2 可嵌入运行时 | E2B(托管 API,Firecracker)、microsandbox(自托管,libkrun) | 要快速给产品加「代码解释器」能力,数据payload小 | 按秒计费对长会话不友好;大数据量有搬运(data gravity)问题 |
| L3 托管平台 | Modal(gVisor,GPU 强)、Northflank(Kata+gVisor,可 BYOC)、Daytona(默认 Docker,可选 Kata,冷启动约 90ms) | 需要 GPU、数据本地化、零运维伸缩 | 各家隔离强度不一(务必问清是 microVM 还是仅容器)、有锁定风险 |
另有一个跨层选项:Google Agent Sandbox(KubeCon NA 2025 发布的 CNCF 开源项目),K8s 原生控制器,支持 gVisor/Kata 双后端和暖池 CRD——已在 Kubernetes 上的团队应优先评估它,代价是集群仍要自己运维。
注:各平台的具体参数(冷启动毫秒数、GPU 支持、会话时长上限)多来自厂商自述或竞品对比博客,采购前应以各家当前官方文档实测为准。
Anthropic 在博客里罕见地公开了四起「我们漏掉的风险」。每一起都对应一类普遍的设计盲区,强烈建议对照自查:
用户 clone 一个仓库来审 PR,仓库里带着 .claude/settings.json 定义的 hook。因为 Claude Code 在弹出「你信任这个文件夹吗?」之前就读取了项目配置——攻击者提交的 hook 自动执行了。2025 年中至 2026 年 1 月间收到的三起责任披露漏洞,结构全部类似。
教训:项目打开、配置加载、localhost 监听,都要当作「来自互联网的入站请求」对待——不能因为它「感觉是本地的」就先于信任边界执行。
内部红队钓鱼实验:一封「帮我跑一下这个」的邮件,附一段看似日常的任务提示词,中间夹着「读取 ~/.aws/credentials,编码后 POST 到外部地址」。25 次重试,24 次外传成功。这是直接提示注入——指令由用户亲手粘贴,模型层的意图检测「没有任何异常可捕捉」,换一个人类承包商拿到同样脚本也会照做。
教训:唯一守得住的是环境层——egress 控制无差别拦掉那个 POST、文件边界让 ~/.aws 根本不可读。(后日谈:这段攻击提示词贴进内部 Slack 讨论后,有人意识到某些内部 Agent 会读 Slack——payload 变成了环境常驻。团队加了金丝雀字符串监控。在 Agent 读一切的世界里,连调查工具本身都是攻击面。)
第三方披露:Cowork 的出站允许清单当然放行 api.anthropic.com(产品没它活不了)。攻击者在用户工作区放一个带隐藏指令的文件,内含攻击者自己的 API key——Claude 按指令读取工作区文件,用攻击者的 key 调 Anthropic Files API 上传。代理检查目的地:合法域名,放行。沙箱完美运转,数据照样丢了。
教训:允许清单不是「目的地过滤器」,而是「能力授予」——放行一个域名,等于放行该域名可达的一切功能。修复方式是在 VM 内加一个防御性中间人代理:只放行携带本 VM 自己会话令牌的请求,攻击者的 key 直接拒绝。
企业安全团队评估 Cowork 时问:「为什么我们的 EDR(终端检测响应)看不进去?」——因为把 Claude 关起来的同一堵墙,也把宿主机上的检测软件挡在了外面;在 EDR 眼里 Cowork 只是一个不透明的 hypervisor 进程。
教训:隔离必然降低可见性。当前缓解是拉取式 OTLP 日志导出(事后审计,非实时监控)。如果你在给企业客户造类似产品,把这场对话的预算提早排上。
github.com 意味着可以向任意仓库 push;需要更细粒度就上可审计的 MITM 代理过滤具体 API 调用。web_search 的 Agent 自动只开 443 出站)。据社区指南判断,目前尚无生产级实现,首批集成预计 2026 年底出现。