给 Claude Code 加沙箱:与其每次求批准,不如约束环境

会写代码、会跑代码的 agent,在你不用盯着它时最有用。但 agent 跑的每条命令也都是风险:一个手滑的 rm、一个意料之外的网络调用、一段读了它不该读的密钥的脚本。

我们管理这类风险的常规办法,是让用户批准动作——但批准这件事不可扩展,而且会把人训练成「不假思索点 yes」。

沙箱(sandboxing)给出另一条路:与其为每个动作求权限,不如约束环境本身,让即便一个不受限的 agent 也造不成真正的破坏。这篇讲我们怎么把 OS 级沙箱带进 Claude Code。


两道边界:文件系统与网络

一个有用的沙箱要管两件事:agent 能什么,以及 agent 能够到什么。

边界管什么效果
文件系统隔离进程能读写哪些文件和目录agent 在项目目录里自由干活,但读不到你的 SSH 密钥、也写不到工作区之外
网络隔离进程能跟哪些主机通信agent 够得到它需要的包管理仓库,但没法把数据导出到任意服务器

这两道边界合起来,能兜住绝大多数可能出岔子的情况。一条命令既逃不出项目目录、又没法往家里打电话,它能造成的破坏就被狠狠地限制住了。


为什么这比批准弹窗强

批准弹窗是为每个潜在危险动作都塞一个人进环里。听着安全,其实有两个问题:

  1. 不可扩展 —— 一个真在干活的 agent 会产生太多太多弹窗。
  2. 更糟的是会「习惯化」(habituation) —— 当你被要求批准第一百条无害命令时,你已经不读了,反射性地就批了。那个本该保护你的弹窗,变成了噪音。

沙箱把这个模型翻了过来。因为环境本身是安全的,agent 可以在里面完全不弹窗地自由跑。你把人的判断留给那个真正需要跨边界的罕见动作,而不是花在常规操作上。


我们怎么做的

沙箱的底层原语各操作系统不同,所以我们是在各平台的原生设施上搭的:

平台用的机制
macOSSeatbelt(sandbox-exec)定义文件系统与网络策略
Linuxnamespaces + seccomp-bpf 过滤器实现等价隔离

我们把这些打包成了一个开源库,所以同一套沙箱原语在 Claude Code 之外也能用。设计目标是:开沙箱这件事,不该让 agent 或用户去操心机制——你声明什么被允许,操作系统负责强制执行。


网络规则靠代理来管

文件系统规则相对好表达,就是一串路径白名单。网络规则更刁钻:你通常不想要「全部放行」或「全部禁止」,你要的是「这些主机,行;其余一切,不行」。

为此,沙箱里的网络流量会被路由经过一个代理(proxy),由它强制执行一份主机白名单。发往已批准域名(比如你的包管理仓库)的请求放过去;发往未知主机的请求被拦下。这样你就拿到了对出站流量(egress)的细粒度控制,而不必提前把每个 IP 地址都预测出来。


沙箱与权限一起用

沙箱不是要取代权限系统——而是补充它。有了沙箱,信任模型就变了:

正是这一点,让 agent 能长段自主地干活,又不牺牲安全。沙箱处理常规,人处理例外。


总结

沙箱运行时是开源的,已经集成进 Claude Code。如果你自己造 agent,也可以用同一个库给它们一个安全的行动环境。

我们认为这是代理式编码(agentic coding)未来的关键一环:不是要求 agent 完美可信,而是搭出一种它不必完美可信也无妨的环境

本译文采用 CC BY-NC-SA 4.0 协议发布,仅供学习交流。

原作品版权归 Anthropic(Anthropic Engineering)所有,原文请见 这里