04 · 审批与沙盒:它能动什么
这是整本手册最该先读的一篇。
两层控制,管的不是一回事
Codex 的安全控制由两层配合完成,很多人一开始会把它们搞混:
- 沙盒模式(
--sandbox):它执行命令时,技术上能做到什么——能写哪些位置、能不能联网。 - 审批策略(
--ask-for-approval):哪些动作必须先停下来问你——离开沙盒、访问网络、运行不受信任的命令。
一个是能力上限,一个是打断你的频率。两者是乘法关系: read-only + never 是最安静也最无害的组合;danger-full-access + never 是完全放开。
默认情况下,智能体在关闭网络访问的状态下运行,写入范围限制在当前工作空间内。
沙盒模式
| 模式 | 能做什么 |
|---|---|
read-only | 只能读。想改文件、跑命令、联网都得走审批 |
workspace-write | 在工作空间里读写、跑命令;默认不能联网 |
danger-full-access | 没有沙盒限制 |
「工作空间」不只是当前目录——还包括 /tmp 之类的临时目录。 拿不准的时候用 /status 看一眼当前会话到底把哪些目录算进了工作空间。
可写根目录里仍然有只读的地方
即使在 workspace-write 下,这几个路径仍然受只读保护,而且是递归的:
<可写根目录>/.git(无论它是目录还是gitdir: ...指针文件;是指针的话,解析出来的真实 Git 目录也一起保护)<可写根目录>/.agents(作为目录存在时)<可写根目录>/.codex(作为目录存在时)
这个设计很实在:智能体可以在你的仓库里随便改代码,但改不了 Git 元数据本身, 所以 git diff / git checkout 这条退路始终有效。
联网是单独一个开关
workspace-write 默认禁网。要开:
[sandbox_workspace_write]
network_access = true开了之后如果还想限制它能连哪里,再打开网络代理:
[features.network_proxy]
enabled = true
domains = { "api.openai.com" = "allow", "example.com" = "deny" }注意:只加域名规则不会自动启用代理,enabled = true 得单独写。
审批策略
| 值 | 什么时候问你 |
|---|---|
untrusted | 只自动执行已知安全的读取操作,其余都问 |
on-request | 需要越过沙盒边界时问(默认的 Auto 用的就是它) |
never | 从不问;在你设的沙盒限制内尽力执行 |
--ask-for-approval never(简写 -a never)不等于放开权限——它对所有 --sandbox 模式都适用, 沙盒该拦还是拦。真正放开是 --sandbox danger-full-access。
用 untrusted 时,可能改变状态或触发外部执行路径的命令都要审批, 包括破坏性的 Git 操作,以及带 Git 输出标志、配置覆盖标志的命令。
六种常见组合
| 用途 | 命令 | 效果 |
|---|---|---|
| 自动(默认) | codex,等价于 --sandbox workspace-write --ask-for-approval on-request | 工作空间内随便干;出界或联网要审批 |
| 只读讨论 | --sandbox read-only --ask-for-approval on-request | 能读能答;要改要跑要联网都得审批 |
| CI 里只读跑 | --sandbox read-only --ask-for-approval never | 只读,绝不打断 |
| 自动改但命令要审 | --sandbox workspace-write --ask-for-approval untrusted | 文件随便改,不受信任的命令先问 |
| 自动审核 | --sandbox workspace-write -a on-request -c approvals_reviewer=auto_review | 边界不变,但审批交给审查智能体,不弹给你 |
| 危险的完全放开 | --dangerously-bypass-approvals-and-sandbox(别名 --yolo) | 无沙盒、无审批(不推荐) |
关于 --yolo
它确实好用,尤其在一个你随时能扔掉的容器里。 但在你自己的开发机上、在有未提交改动的仓库里用它,本质上是拿工作赌它这次不会跑错命令。 真需要放开,先想想能不能换成 Dev Container 或工作树,把风险关在一个盒子里。
把审批交给审查智能体
如果审批提示太多、但又不想直接 never,还有一条中间路:
approval_policy = "on-request"
approvals_reviewer = "auto_review"设成 auto_review 之后,符合条件的审批请求会先交给一个审查智能体, 它按策略检查数据外泄、凭据探测、削弱安全防护、破坏性操作这几类风险: 低风险和中风险放行,严重风险拒绝,高风险需要充分的用户授权。 提示构建、审查会话或解析失败时默认拒绝。
代价是它会额外调用模型,所以会多花额度。管理员可以用 allowed_approvals_reviewers 限制谁能用。
还有一种更细的做法,让某些类别保持交互式、其余自动拒绝:
approval_policy = { granular = {
sandbox_approval = true,
rules = true,
mcp_elicitations = true,
request_permissions = false,
skill_approval = false
} }写进 config.toml,别每次敲标志
# ~/.codex/config.toml
approval_policy = "on-request"
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = false也可以存成多个配置方案,按场景切换:
# ~/.codex/readonly_quiet.config.toml
approval_policy = "never"
sandbox_mode = "read-only"codex --profile readonly_quiet我的建议
- 日常在自己仓库里:默认的
Auto就挺好,别急着调。 - 看一个不熟的仓库:
--sandbox read-only,先让它读懂再说。 - 跑在 CI 里:
--sandbox read-only --ask-for-approval never,要写的话再单独放开。 - 审批烦到影响干活:先试
auto_review或细粒度策略,再考虑never。 - 想彻底放开:先把工作放进容器或 Git 工作树。