Codex 沙箱三种模式怎么选:从「能不能改我的文件」倒推

2026-08-09

选沙箱模式这件事,大部分人是反过来做的:先看官方文档列了三个值,再猜哪个”比较安全”,最后被拦住了就往下调一档,一路调到 danger-full-access 为止。这个顺序很容易把边界一次性拆光。

更省事的顺序是先回答一个问题:这一轮,我允许它动我磁盘上的哪些东西? 答案一旦确定,模式基本就定了,剩下的都是补丁式的微调。

三个值,先看官方原话

Codex(OpenAI Codex)的 CLI 侧用 -s, --sandbox <read-only|workspace-write|danger-full-access> 指定,配置侧对应 config.toml 里的 sandbox_mode。三个取值的官方释义是这样的:

模式官方原文
read-only”The agent can inspect files, but it can’t edit files or run commands without approval.”
workspace-write”The agent can read files, edit within the workspace, and run routine local commands inside that boundary.”(官方标注这是默认模式
danger-full-access”The agent runs without sandbox restrictions. This removes the filesystem and network boundaries and should be used only when you want the agent to act with full access.”

把这三句话按”能不能写盘”重排一下,决策就出来了:

  • 只想让它读代码、解释逻辑、给方案、做定位——它压根不需要写权限,那就 read-only。注意官方这句话的后半段:在这个模式下,连”跑命令”也是要审批的,不只是编辑文件被挡。
  • 想让它在当前项目里改文件、跑常规本地命令——workspace-write。这也是默认档,边界是”workspace 之内”。
  • 只有在你明确要它越过文件系统与网络边界时,才轮到 danger-full-access。官方自己给的措辞是 “should be used only when”,这是一句限定,不是一个推荐。

最容易混的一件事:沙箱不是审批

这是我见过最多人栽的地方。Codex 有两套独立的旋钮:

一套是沙箱sandbox_mode),管的是”边界在哪”;另一套是审批策略approval_policy / CLI 的 -a, --ask-for-approval),管的是”越界或者动手之前要不要问你”。CLI 侧三档审批的官方释义分别是:untrusted 只有受信任命令(如 ls、cat、sed)免审批,其余升级给用户;on-request 由模型决定何时请求审批;never 从不询问,执行失败直接回传给模型。

关键判断依据:never 不等于”放开权限”。它改变的只是”要不要问你”这件事,沙箱边界原封不动地还在——命令失败了它就把失败结果吞回去继续想办法,而不是获得了额外权力。真正撤掉边界的是 danger-full-access,或者顶层那个 --dangerously-bypass-approvals-and-sandbox(官方原文写的是 “EXTREMELY DANGEROUS. Intended solely for running in environments that are externally sandboxed”)。

所以”我设了 never 它还是改不了 C:\ 下的文件”不是 bug,是你调错了旋钮。反过来,“我用了 danger-full-access 结果它每一步还在问我”也不是 bug,是审批那一档没动。

顺带一提,CLI 还有个 --approve-for-me:审批请求走自动复核,且使用 workspace-write 沙箱。它同时决定了两个旋钮,用之前心里要有数。

审批策略还有一个容易被忽略的形态:approval_policy 既可以是一个字符串(粗粒度三档),也可以是一张表,表里有 approval_policy.granular.sandbox_approval.rules.mcp_elicitations.request_permissions.skill_approval 五个布尔开关。想”只放行某一类弹窗”,就必须用表形式,字符串做不到。另外还有 approvals_reviewer,默认 user,可以设成 auto_review

边界不够用时,别急着跳最后一档

真实场景里最常见的诉求是:项目在 A 目录,但构建产物要写到 B 目录。这时候的正确动作不是切 danger-full-access,而是在保留沙箱的前提下把 B 加进可写范围:

  • 配置侧:sandbox_workspace_write.writable_roots,给 workspace-write 追加额外可写根
  • 命令行侧:--add-dir <DIR>,主工作区之外额外的可写目录

同一组配置下还有几个相关键:sandbox_workspace_write.network_access(workspace-write 沙箱内是否允许出网)、sandbox_workspace_write.exclude_tmpdir_env_var(把 $TMPDIR 排除出可写根)、sandbox_workspace_write.exclude_slash_tmp(把 /tmp 排除出可写根)。

出网是另一个独立维度,值得单拎出来说:在 workspace-write 下能不能联网由 sandbox_workspace_write.network_access 决定,跟”能不能写文件”不是一回事。想要更细的域名级控制,官方文档给的做法是走 permissions.<name>.network.domains.<pattern>(取值 allow / deny,支持精确主机名与通配),以及 experimental 阶段的 features.network_proxy——注意这一项官方标着 experimental,不要当稳定能力铺到团队里。对使用 ChatGPT Work(web)的团队,官方文档给的做法是去 Settings > Data controls > Work network access,关闭后命令只能访问必需主机名的允许列表;这一条我们没有实测,属于官方口径。

一个可以直接抄的起手配置:

sandbox_mode = "workspace-write"
approval_policy = "on-request"

[sandbox_workspace_write]
network_access = false
writable_roots = ["<你的额外可写目录>"]

以上为按官方文档键位组合的示例,未逐项实测,以官方文档为准。

三个平台不是一套机制

这是排错时最值钱的一条背景知识:Codex 的沙箱在三个平台上是三套不同的实现。

  • macOS:使用系统内置的 Seatbelt 框架
  • Windows:在 PowerShell 中使用原生 Windows 沙箱;在 WSL2 里则走 Linux 的那一套
  • Linux / WSL2:需要用包管理器安装 bubblewrap(bwrap)

判断依据很直接:Linux 上遇到”沙箱不生效、起不来”,第一件事是查 bwrap 装没装;而 Windows 上完全是另一套机制,不要把 Linux 的排查步骤套过来。搜到的教程里一大半是 Linux 视角的,照着做只会浪费时间。

Windows 侧:elevated 还是 unelevated

Windows 上的原生沙箱在 PowerShell 中运行,强制受限的文件系统与网络权限,不需要 WSL、也不需要虚拟机。它有两个模式:

模式特征
elevated(官方标注为首选使用专用的低权限沙箱用户;文件系统权限边界加防火墙规则;需要管理员批准的初始化设置
unelevated(回退)用”从当前用户派生的受限 Windows token”运行命令;基于 ACL 的文件系统边界;用环境级离线控制替代防火墙规则;保护更弱,但在拿不到管理员批准时可用

配置键是 windows.sandbox,取值 "unelevated""elevated";另有 windows.sandbox_private_desktop,默认 true,表示默认在私有桌面上运行沙箱子进程。

所以这一档的判断依据不是”哪个更好”,而是你这台机器能不能拿到管理员批准。拿得到就用 elevated;公司机器 UAC 被管住、本地用户创建被阻止的,就回退 unelevated,同时接受官方自己写明的”保护更弱”这个前提——不要因为它跑起来了就把它当成和 elevated 等价。

系统版本也是硬条件:Windows 11 是推荐,较新的 Windows 10(v1809+)是尽力而为(best effort),更老的 Windows 10 不推荐。另外有一条硬性要求:winget 必须可用。

初始化失败的常见原因,官方列了三条:拒绝了 UAC 提示、本地用户创建被阻止、防火墙规则被限制。有一个专门的错误值得记住——错误 1385,官方原文是 “Windows is denying the logon type the sandbox user needs.”,含义是沙箱用户已经建好了,但策略不允许它执行命令。官方给的排查顺序是四步:① 重启 Codex ② 重试 elevated 初始化 ③ 需要时回退到 unelevated ④ 发送诊断,日志在 CODEX_HOME/.sandbox/sandbox.log。这四步之外的注册表改法、组策略改法,官方文档没给,我也不会替它编一个。

还有两个现象别误判成故障:某些任务会故意在无出网的状态下运行,取决于权限模式;如果某个目录是”writable by Everyone”(对所有人可写),Codex 会告警,提示 Windows 权限过宽——这是在提醒你系统侧的 ACL 太松,不是 Codex 出错。

本机能验证到什么

在 codex-cli 0.147.0(Windows 11)上,有几条只读观测可以帮你确认自己没记错:

第一,取值只有那三个,写错会当场被挡住。执行 codex -s bogus-mode,报错是:

error: invalid value 'bogus-mode' for '--sandbox <SANDBOX_MODE>'
  [possible values: read-only, workspace-write, danger-full-access]

第二,沙箱是真的在拦写入。在同一环境下用 codex sandbox 跑一条往仓库路径写文件的无害命令,命令返回之后目标文件并不存在——默认沙箱状态下这次写入没有落盘。

第三,codex sandbox--sandbox-state-* 选项是一组的。单独给 --sandbox-state-disable-network 而不给 --sandbox-state-json,会直接报缺少必需参数;也就是说必须先有一份 state JSON,才能在它之上做增删。

第四,想看当前生效的边界,跑 codex doctor。在这台机器上,Configuration 分组里 sandbox 那一行显示的是 restricted fs + restricted network · approval OnRequest——沙箱状态与审批档位在同一行里,正好对应上文那两个旋钮。同一台机器的 ~/.codex/ 下确实存在 .sandbox/.sandbox-bin/.sandbox-secrets/ 三个目录,config.toml[windows] sandbox = "elevated"

要提醒一句:以上都是 0.147.0 这个版本、这台 Windows 11 机器上的观测,默认值和特性阶段都会随版本变,别把它当成”Codex 永远如此”。

收个尾:三个问题决定一档

真到要选的时候,按顺序问自己三句话就够了:

  1. 这一轮它需要写盘吗? 不需要 → read-only,顺手把审批留在 on-requestuntrusted
  2. 需要写盘,但只在项目里?workspace-write(默认档)。范围不够就加 writable_roots--add-dir,别整个拆掉。要不要出网单独由 network_access 决定。
  3. 确实要越过文件系统与网络边界? → 先确认这台机器本身是不是已经被外部沙箱化了(容器、一次性虚拟机、CI 的临时机器)。是,danger-full-access 才谈得上合理;不是,那就回第 2 条老老实实加目录。

Windows 用户额外加一问:管理员批准拿不拿得到。拿得到走 elevated,拿不到走 unelevated 并且心里记着它保护更弱。出问题先看 CODEX_HOME/.sandbox/sandbox.log,不要拿 Linux 的 bwrap 排查思路往上套。

相关阅读


本文依据 Codex 官方文档(learn.chatgpt.com/docs/ 的《Sandbox》《Windows sandbox》《Configuration Reference》页面)整理,核对日 2026-08-09;文中标注「本机实测」的部分基于 codex-cli 0.147.0 / Windows 11 环境下的只读命令输出。产品功能、模型与价格以官方最新说明为准。桌面应用与云端部分为官方文档口径,非本机实测。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。