Claude Code、CodeX 这类 AI Coding Agent 在我日常的工作当中基本上已经离不开了,用它们写出来的代码基本上能够满足我的要求,说实话写的代码比我自己写的都要好。
在使用的过程当中,基本上每个工具都有如下的权限设置,每个档位都对应着 Agent 能访问或者操作的权限边界。

这个权限功能的本质就是一套运行在客户端的沙箱(sandbox)系统。
因为自己本身也是开发,所以非常想详细的了解一下这个沙箱系统是怎么实现的,顺便也自己尝试一下构建一个自己专属的 Coding Agent 来替自己干活。
为什么需要沙箱
在正式开始之前,需要先了解一下为什么需要沙箱系统?
因为如果直接给 Agent 提供完整的真实环境,而 Agent 执行了某些不可逆的操作之后直接就修改了原本系统的状态。
比如由于幻觉、误判直接把服务器上的某些重要数据或者文件删除,又或者因为使用了来历不明的 MCP 、Skills或者中转站等,被恶意注入了一些危险指令。
想象一下这样的场景:
让 AI 帮忙写个 python 脚本用来导出数据,它直接顺手 rm -rf 删掉了一些你根本没让它改的文件。
让它跑个项目里的测试代码,它直接读取了电脑上的各种私钥信息。
你以为你给它写好 prompt 让它自己干活就好了,其实暗地里它把 .env 里的密钥偷偷发送到某个未知的服务器上了。
当一个 Coding Agent 可以"自己输出命令并且自己跑",它就像一个黑盒一样,输出的命令你根本没发控制。
这样做的本质上就是把一段不可信代码放进你的电脑里并且直接执行。
那么问题来了:在这种情况下,你敢直接按回车吗?
没错,别犹豫,这个时候你就需要沙箱工具。
沙箱工具做的事情本质非常朴素,就是直接给 Agent 套上一件枷锁,让他带着镣铐来实现需求,它无法碰到我们没有授权给它做的事情,这样它就碰到你的密钥、不会胡乱删除系统的文件也不会在执行恶意脚本的时候给未知的域名发生信息。
六条设计原则
不管是 Codex、Claude Code,还是自己来实现一个 Coding Agent,沙箱的设计基本都绕不开下面这几条原则。
理解了六条规则之后,后面看Codex 和 Claude Code 的实现会轻松很多。
默认拒绝,而不是默认放行
能不开放权限就不开放权限,用白名单而不是黑名单思维。
Codex 的 workspace-write 模式,默认除了当前的工作目录之外,其它任何幕都默认都是只读; Claude Code 默认不允许请求任何公网域名,有新域名第一次需要访问的时候,会向用户请求授权。
最小权限
只给工作目录写权限,网络允许默认都关闭,密钥文件(~/.ssh、~/.aws、.env)对 Agent 不可见。 Claude Code 还能显式把某些文件和环境变量 deny 掉。
隔离要分四个维度
文件系统、网络、进程、系统调用,一层层收。
只锁文件不够,Agent 能读能写,联网一样可以把数据发走;
只锁网络也不够,它能改你本地的 git config,直接把代码推送到未知仓库。
必须要实现四个维度的一起限制才有作用。
把"策略"和"怎么落地"分开
这点我觉得设计得非常厉害。
写一套"我想要什么隔离级别"的策略描述,背后按客户端所处的操作系统映射到不同的原生机制:macOS 用 Seatbelt,Linux 用 bubblewrap 加 seccomp,Windows 用受限令牌加 ACL。上层只管策略,下层管落地。
自治和安全的取舍
沙箱越严格,Agent 越能连跑不中断。
反过来,如果 Agent 的每一步操作都需要人工审批,按了二十次 Approve 之后基本上就是在无脑点了,这才是真正的安全幻觉。
沙箱本质上是在用系统级边界,来换使用者有限的注意力。
纵深防御,别神话它
沙箱不是银弹,它只是第一道墙,需要配合权限模型、代码审查、依赖审计叠一起用。

落地:CodeX 和 Claude Code 沙箱方案探索
Codex:三套原生隔离,藏在统一策略后面
Codex 的沙箱是典型的"策略抽象 + 多平台实现":
- macOS 12+ :用系统自带的 Seatbelt 加
sandbox-exec工具。能够根据 Agent 请求的权限等级动态生成一份 SBPL(Sandbox Profile Language)权限控制脚本。 - Linux : bubblewrap(bwrap)加 seccomp 的组合。bwrap 用 mount namespace 把根目录设置成只读,再把工作目录设置成可写;seccomp 工具在进程内拦掉
connect/bind/ptrace等系统调用。 - Windows:用受限令牌(restricted token)加 ACL 来修改改文件权限,再用专门的 IPC 提权的运行器来执行。
权限分级跨平台通用:ReadOnly(只读挂载)、WorkspaceWrite(工作区可写、敏感目录强制只读),Linux 上网络还有三档 Isolated / ProxyOnly / FullAccess。
Claude Code:sandboxed Bash tool
Claude Code 也有 OS 级沙箱,不是只靠权限审批。
Claude Code 提供的是一个 sandboxed Bash tool,给 Bash 命令做文件系统和网络隔离,底层 macOS 用 Seatbelt、Linux/WSL2 用 bubblewrap(再加 socat 做网络代理)。原生 Windows 不支持,得跑在 WSL2 里。
参考文档: code.claude.com/docs/en/san...
开启方式很简单:
- 会话里敲
/sandbox,选 auto-allow 或 regular permissions;

- 或者在
.claude/settings.local.json/~/.claude/settings.json进行配置,配置内容如下:
json
{ "sandbox": { "enabled": true } }
隔离策略:
- 文件系统 :当前工作目录和会话临时目录默认可写,但全机可读。需要注意的是,默认情况下它还能读到
~/.ssh这类东西,除非开发者显式 deny。 - 网络 :默认不预放行任何域名,新域名首次出现会向用户索取放行权限;可以用
allowedDomains预放行。 - 密钥 :能显式 deny 文件或环境变量,比如把
GITHUB_TOKEN设成 deny。
它和权限审批是两层互补的关系:权限规则管"工具能不能跑"(所有 tool 通用,运行前生效),沙箱管"Bash 跑的时候 OS 层怎么隔离"(只管 Bash,运行时生效)。/sandbox 不是另一种权限模式,二者是叠在一起的。
对比
| Agent | Codex | Claude Code |
|---|---|---|
| 隔离层级 | OS 原生(Seatbelt / bwrap+seccomp) | OS 级 Bash 沙箱(Seatbelt / bubblewrap) |
| 策略抽象 | 统一沙箱策略 + 多平台实现 | 权限模型 + Bash 沙箱 |
| 默认行为 | 按 --sandbox 等级(ReadOnly / WorkspaceWrite) |
配置开启;命令走权限审批 |
| 网络策略 | 默认禁止(按等级划分,Linux 有 Isolated/ProxyOnly/FullAccess 不同的等级) | 默认不预放行,新域名向用户请求;可以配置预放行列表 |
| 平台覆盖 | macOS / Linux / Windows | macOS / Linux / WSL2(原生 Win 不支持) |
| 密钥保护 | 敏感目录强制只读(.git/.agents/.codex) | 需显式配置禁用的文件或者变量;默认为电脑上所有文件可以读取 |
实测
Codex(macOS) 选择 workspace-write 模式之后后,实际生成的 SBPL 大概如下面所示:
arduino
(version 1) ; 声明版本号
(deny default) ; 默认拒绝
(allow process-exec*) ;运行执行程序
(allow file-read* (subpath "/")) ; 全机可读
(allow file-write* (subpath "/path/workspace")) ; 工作区可以写
(deny file-write* (subpath "/path/workspace/.git")) ; 敏感目录强制只读
(deny file-write* (subpath "/path/workspace/.agents"))
(deny file-write* (subpath "/path/workspace/.codex"))
(deny network*) ; 默认禁止访问通过网络外部
逐行看:deny default 是默认拒绝;file-write* 只放开工作区;.git 那三行强制只读,防它改 git config;最后 deny network* 把外联掐了。
我们也可以自己在电脑上测试一下 sandbox-exec 禁止所有网络请求的情况,如下图所示:

sandbox-exec 命名是 macos 自带的,直接在终端当中就可以使用:
perl
sandbox-exec -p '(version 1)(allow default)(deny network*)' curl https://www.dimples.top/
第一条命了,我们默认允许所有但是禁用了网络,也就是(deny netwotk*),使用 curl 请求自己的博客地址发现直接无法解析域名。
去掉网络限制之后,请求如下图所示:

命令如下:
perl
sandbox-exec -p '(version 1)(allow default)' curl https://www.dimples.top/
Codex(Linux) 的 bwrap 命令行大致是:
css
bwrap --unshare-user --unshare-pid --unshare-net \
--ro-bind / / \
--bind /path/to/workspace /path/to/workspace \
--bind /path/to/workspace/.git /path/to/workspace/.git --read-only
--unshare-net 直接把网络 namespace 摘掉,--ro-bind / / 把根挂只读、再 bind 回工作区可写。配 seccomp 拦 connect / bind,四个维度就齐了。
Claude Code 你开 /sandbox 后跑同一条 curl api.github.com,会看到它被代理拦下、弹 prompt 问你要不要放行这个域名,这就是网络隔离在运行时生效的证据。
没有绝对的安全
到这里,我们必须知道沙箱也不等于绝对的安全,不能过度的神话它。比如下面这些情况也能绕过沙箱直接提权进行某些非授权操作。
- 供应链投毒 :恶意 npm 包在沙箱内照样能外联、读项目内自己的
.env(它就在工作区里,沙箱管不着); - 0day / 逃逸:OS 级沙箱也可能被逃逸(bwrap/seccomp 历史上都有过);
- 配置错误 :Codex 容器里主机不支持 Landlock/seccomp 时沙箱可能静默失效;Claude Code 依赖没装(bubblewrap/socat)时默认只是 warning 然后直接运行,除非你设了
failIfUnavailable: true。
我的看法是:沙箱的价值不是消灭风险,而是把大概率翻车的事件压到一个能接受的范围。真要用 Agent 写代码,还是得配合代码审查、依赖审计,以及最小权限账号一起上。
总结
上面就是我这几天学习 Coding Agent 沙箱的笔记。后面我打算用学到的东西,自己搓一个专属的 Coding Agent 来干点脏活累活,到时候再写实战篇。
如果这篇对你有点用,关注一下不亏,后面还有更硬的实操。也欢迎在评论区聊聊你踩过 Agent 的坑,我挺想看真实案例。