装上一个沙箱,agent 就安全了?Anthropic 开源的 sandbox-runtime 给出的答案没那么简单:它默认拒绝文件写入和网络访问,但读取权限默认全开——~/.ssh、云凭证、.env 文件并不会因为你装了沙箱就从 agent 视野里消失。
这个项目以 npm 包 @anthropic-ai/sandbox-runtime 发布,版本 0.0.81,Apache-2.0 许可,engines 字段要求 Node >=22.12.0。解包后约 11.4 MB,大头是面向 x86-64 和 arm 的预编译 seccomp BPF 过滤器。命令行工具叫 srt,库接口是 SandboxManager.initialize(config) 加 wrapWithSandbox()。
README 把它标为 Beta Research Preview,并说明 API 和配置可能变化;Windows 支持标注为 alpha。这两条对打算今天就把放进生产链路的团队来说,是必须先看的。
默认策略的三句话
README 用三句话定下了边界:默认允许在所有位置读取;默认拒绝在所有位置写入,必须显式放行路径(比如 . 和 /tmp),空允许列表等于没有写权限;默认拒绝所有网络访问,必须显式放行域名,空 allowedDomains 列表等于没有网络。
这里的不对称值得细读。写入和网络是"只允许"模式:列表为空就没有权限。读取是"先拒后允":除非你在 denyRead 里点名某个区域,否则一切可读。所以凭证文件不会自动隐身,你得自己把它们列出来。部署翻车的第一个坑就在这里——把"已沙箱化"当成"凭证已安全"。
边界靠操作系统原语执行
macOS 上,运行时生成 Seatbelt 配置,用 sandbox-exec 跑命令。Linux 上用 bubblewrap 做容器化并隔离网络命名空间,再叠加 seccomp 过滤器在 x64 和 arm64 上拦截 Unix socket。Windows 的 alpha 路径则把进程放在专用的 srt-sandbox 本地账户下,配 Windows Filtering Platform 出站围栏、写受限令牌和工作树的显式 ACL。
限制作用于整个进程树,脚本和子进程一并继承。网络也不是敞开的:流量被强制走宿主机上的 HTTP 和 SOCKS5 代理,Linux 通过绑定挂载进沙箱的 Unix socket,macOS 通过允许一个 localhost 端口的 Seatbelt 规则。域名的放行与拒绝在沙箱之外的代理里决定,沙箱内部只有一扇窄门。
它挡不住什么
内核漏洞不在覆盖范围内。策略管的是文件、网络和进程树,而它和你机器上其他东西跑在同一个内核上。内核 bug、Seatbelt 或 seccomp 绕过、提权,都在这条边界之外。README 并未声称内核级隔离,这个判断是从所用原语推出来的。如果你的威胁模型包含内核漏洞利用,需要的是虚拟机或另一台机器。
配置失误同样致命。默认保护的是写入和网络,不是读取。打开 allowAllUnixSockets 会关掉 Linux 上的 seccomp 拦截;enableWeakerNestedSandbox 为 Docker 环境启用更弱的模式;allowNestedUserNamespaces(默认 false)允许命令创建自己的用户命名空间,README 说在其下运行的命令,denyWrite 和强制拒绝项都视为不成立。每一个开关都是拿隔离换兼容。
允许列表也可能被滥用。一个放行的域名就是一条通道:如果 agent 能访问任何接受上传的主机,或者你为构建步骤放行的某个域名,这条路就能把数据带出去。代理缩小了面,但没有消除把列表压短的必要。用 registerCommandNetworkLists 注册的按命令列表需要至少 22 个字符的 commandId,且永远不会覆盖已配置的 deniedDomains——适合单次构建,不是悄悄放宽策略的手段。
Beta 状态和平台缺口也要算进去。Beta 意味着配置格式会动。Windows 路径是 alpha,README 记录的缺口包括:SMB 共享和 WSL 流量不受 WFP 围栏覆盖,因为这些连接由系统服务而非沙箱进程发起。Ubuntu 24.04 及以后版本,默认的 AppArmor 限制会剥夺非特权用户命名空间的能力,而 bubblewrap 和 seccomp 层都需要它,解法是一个 sysctl 或 AppArmor 配置。以 root 运行需要 CAP_SETFCAP。Linux 上代理通过 HTTP_PROXY 及相关变量配置,忽略这些变量的程序就没有网络。
上线前的五道检查
- 从空的写入和网络列表起步,只把任务真正需要的加回来。allowWrite 应该是 . 加一个具体临时路径,不是你的主目录;allowedDomains 应该从 [] 开始。
- 把凭证的读取拒绝列全:~/.ssh、~/.aws、~/.config,以及项目里的 .env 文件。读取默认全开,这一步最常被跳过。
- 打开违规上报并接到某个地方。给 wrapWithSandbox 传稳定的 commandId 和 commandText,再用 getViolationsForCommand() 收集拒绝记录。没有 commandId 时,键是命令字符串且只比较前 100 个字符,共享前缀的长命令会串账。
- 盯住削弱边界的开关。allowAllUnixSockets、enableWeakerNestedSandbox、allowNestedUserNamespaces 应该出现在评审里,而不是埋在配置文件中。打开其中一个的 diff 就是一次安全变更。
- 在 CI 里跑同一套策略。给依赖安装步骤放行它需要的仓库域名,然后为测试清空 allowedDomains。macOS 和 Linux runner 都跑,并在信任 Linux 结果之前处理好 Ubuntu 24.04 的 AppArmor 设置。
它适合放在哪
对单机跑 agent、CLI 工具或 MCP 服务器的场景,这是缩小爆炸半径的便宜办法,用一条边界替代逐步审批。但当你执行不可信代码、在同一台主机上跑多租户、或把内核 bug 计入威胁模型时,它替代不了虚拟机。它也不意味着每个项目都该采用——合适的默认值,取决于你允许 agent 碰什么。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.