沙箱与权限
给 Codex 戴上安全帽 —— Config Profiles 让不同场景拥有不同边界
3 种沙箱模式 · 3 种审批策略 · 多 Profile 管理总是在事后才发现?
那些"早知道就该拦住它"的瞬间
它删了我不想删的文件
Codex 执行 git clean -fd 时你心头一紧 —— 那些未跟踪的配置文件就这样消失了。没有任何确认环节。
它在后台悄悄联网
Codex 调用了外部 API,把项目数据发了出去。你甚至不知道它做了网络请求。没有网络访问限制。
每次弹确认太烦了
你在做本地实验,Codex 每次写文件都要你点"允许"。第 20 次的时候你开始无脑回车,安全机制形同虚设。
开始之前
适合谁读
- 已经日常使用 Codex CLI,想加固安全边界的团队
- 需要给不同项目配置不同权限的安全工程师
- 希望统一团队 Codex 行为规范的 Tech Lead
读完你应该已经能
- 理解 3 种沙箱模式的差异与适用场景
- 配置 approval_policy 控制命令审批流程
- 使用 Config Profile 管理多套权限配置
- 排查常见沙箱相关错误与权限问题
暂时不碰
- 沙箱底层的 Linux namespace 实现细节
- subagent 内部沙箱继承规则
- 企业级 Codex 部署的组策略管理
沙箱是什么?
给 Codex 戴上"安全手套"
沙箱(Sandbox)是 Codex 运行命令时的隔离环境。它决定了 Codex 能读哪些文件、能写哪些文件、能否访问网络。
一句话理解
沙箱 = 一个"虚拟的工作空间"。Codex 内部的操作(读/写/删/网络)都被限制在这个盒子里。盒子之外的资源,Codex 碰不到。
为什么需要它?
- 防止误操作:删库跑路的命令被拦截
- 防止数据泄露:敏感文件不可被读取
- 防止外部通信:不期望的 API 调用被阻止
# config.toml —— sandbox_mode 是顶层键
sandbox_mode = "workspace-write"
模式一:read-only
只读沙箱 —— 最安全的观察者
read-only 模式下,Codex 不能修改任何文件。它只能读文件、运行不会产生副作用的命令。
谁能做什么?
- ✅ 读取任意文件
- ✅ 运行只读命令(
ls、cat、git status) - ❌ 写入任何文件
- ❌ 执行写操作(
rm、git push)
典型场景
- 代码审查 / review
- 只读对话(问 Codex 问题)
- 安全审计(Codex 分析你的代码但不碰它)
# 只读模式配置
sandbox_mode = "read-only"
模式二:workspace-write
工作区写入 —— 日常开发首选
workspace-write 是推荐默认模式。对受版本控制的目录,Codex 默认使用此模式。它可以在你的项目目录内自由读写文件,但目录外的文件仍然只读,网络默认关闭。
谁能做什么?
- ✅ 读写项目目录内文件
- ✅ 网络可配置开启(需显式设置)
- ✅ 创建、删除项目内文件
- ❌ 修改系统目录(
/etc、/usr) - ❌ 写入其他项目目录
典型场景
- 日常编码任务
- 运行测试和构建
- 安装依赖包(需开启网络)
# workspace-write 配置
sandbox_mode = "workspace-write"
# workspace-write 专属子配置
[sandbox_workspace_write]
network_access = true # 布尔值,不加引号
writable_roots = ["/tmp", "/home/user/data"] # 额外可写目录
模式三:danger-full-access
完全访问 —— 自由但危险
danger-full-access 模式下沙箱几乎不存在。Codex 以你的用户权限执行任何命令,没有文件系统隔离。
谁能做什么?
- ✅ 读写任意文件
- ✅ 执行任意命令
- ✅ 访问网络
- ✅ 安装系统级包
典型场景
- 本地封闭开发环境
- 容器 / VM 内的开发
- 系统级配置任务
# 完全访问(慎用)
sandbox_mode = "danger-full-access"
rm -rf / 也能执行。只在完全信任的环境里启用。三种模式对比
一眼看清差异
| 维度 | read-only | workspace-write | danger-full-access |
|---|---|---|---|
| 项目文件读取 | ✅ | ✅ | ✅ |
| 项目文件写入 | ❌ | ✅ | ✅ |
| 系统文件读取 | ✅ | ✅ | ✅ |
| 系统文件写入 | ❌ | ❌ | ✅ |
| 网络访问 | 默认关闭 | 可配置开启 | ✅ |
| 风险等级 | 🟢 低 | 🟡 中 | 🔴 高 |
| 推荐场景 | 审查/问答 | 日常编码 | 隔离环境 |
审批策略:never
全自动 —— 零打断
approval_policy = "never" 意味着 Codex 不弹任何审批提示。但注意:沙箱限制仍然生效——越界操作会直接失败而非弹窗。
# 全自动模式(approval_policy 是顶层键)
approval_policy = "never"
适用场景
- 已经开启 read-only 沙箱
- CI/CD 非交互自动化流程
- 沙箱已定义清晰边界的场景
⚠️ 风险
- 搭配 danger-full-access 极其危险
- 错误命令没有人工审核环节
审批策略:on-request
按需确认 —— 平衡安全与效率
approval_policy = "on-request" 是官方推荐配置。沙箱内的常规操作自动执行,仅当操作需要越出沙箱边界(如写沙箱外文件、访问网络)时才弹出确认。
# 按需审批(受版本控制目录的默认推荐值)
approval_policy = "on-request"
确认时你会看到什么
- 即将执行的命令内容
- 影响范围(文件路径、网络 URL)
- 选项:允许本次 / 拒绝
与沙箱的协作
沙箱定义技术边界(能写哪里),审批策略定义何时问你。on-request 下沙箱内操作零打断,越界才问——兼顾效率与安全。
审批策略:untrusted
每次确认 —— 最高安全门槛
approval_policy = "untrusted" 下每条命令都需要手动确认。
# 每次命令都要确认
approval_policy = "untrusted"
适用场景
- 处理生产环境配置
- 第一次运行不熟悉的仓库
- 安全审计期间的额外谨慎
缺点
- 每一步都打断,效率较低
- 习惯后容易"机械回车"
- 降低 Codex 的自动化价值
workspace-write + on-request 的组合(官方 "Auto" 预设)。已弃用的 on-failure
曾经的"失败后确认"模式
approval_policy = "on-failure" 在早期版本中存在,命令在沙箱内失败后才请求确认。但官方文档已将其标记为弃用(deprecated)。
官方建议
- 交互式使用 → 改用
on-request - 非交互自动化 → 改用
never codex exec --full-auto同样已弃用
为什么不推荐
- 语义不直观,容易误解
- 权限升级请求行为不符合预期
- 新版本可能随时移除
危险命令拦截
0.144.5:更强的危险命令检测,拒绝原因更清晰
覆盖更多 rm 形式
之前有些"强制删除"的变体(带各种 flag 组合的 rm)能绕过检测。0.144.5 补全了更多强制 rm 形式,减少漏网。
拒绝原因更清楚
被拦截时不再只是干巴巴的"拒绝",而是给出更清晰的原因——告诉你为什么这条命令危险,方便判断是真威胁还是误判。
代理配置统一
0.146:HTTP 代理被各类请求严格遵循
配了代理却仍有请求"漏网"直连,是企业内网最头疼的问题。0.146 起,以下流量全部遵循已配置的代理:
- 认证请求
- Plugin 下载
- MCP 授权握手
- LM Studio 连接
config.toml 配置
用文件定义安全边界
# $HOME/.codex/config.toml —— 全局配置
# sandbox_mode 和 approval_policy 都是顶层键
sandbox_mode = "workspace-write"
# workspace-write 专属子配置段
[sandbox_workspace_write]
network_access = true # 布尔值,不加引号
writable_roots = ["/tmp", "/var/log/myapp"] # 额外可写目录
# 审批策略(顶层键,不是 [approvals] 段)
approval_policy = "on-request"
# 审核者(顶层键)
approvals_reviewer = "user"
$CODEX_HOME/config.toml(CODEX_HOME 默认 ~/.codex),项目级配置放在项目的 .codex/config.toml。项目级配置优先(且需项目受信任)。CLI 运行时覆盖
命令行参数优先级最高
# 覆盖沙箱模式(-s 是 --sandbox 简写)
codex -s read-only
# 覆盖审批策略(-a 是 --ask-for-approval 简写)
codex -a untrusted
# 同时覆盖模型 + 沙箱
codex -m gpt-5.6 -s read-only
# 叠加配置文件 Profile
codex -p oss
| 参数 | 作用 | 示例 |
|---|---|---|
-s / --sandbox | 覆盖沙箱模式 | -s danger-full-access |
-a / --ask-for-approval | 覆盖审批策略 | -a never |
-m / --model | 选择模型 | -m gpt-5.6 |
-p / --profile | 加载额外配置 Profile | -p work |
Permission Profiles(Beta)
用命名 Profile 定义细粒度文件/网络规则
Codex 支持实验性的 Permission Profiles 系统,在 [permissions] 下定义命名 Profile,用文件系统规则 + 网络域名规则实现最小权限。
sandbox_mode/sandbox_workspace_write 设置不能混用。配了 default_permissions 就不要再用 sandbox_mode。# 三种内置 Profile
# :read-only — 只读
# :workspace — 工作区可写
# :danger-full-access — 无限制
# 自定义 Profile 示例
default_permissions = "project-edit"
[permissions.project-edit.workspace_roots]
"~/code/app" = true
"~/code/shared-lib" = true
[permissions.project-edit.filesystem.":workspace_roots"]
"." = "write"
"**/*.env" = "deny" # deny 规则始终优先生效
[permissions.project-edit.network]
enabled = true
[permissions.project-edit.network.domains]
"api.openai.com" = "allow"
"*.github.com" = "allow"
deny 规则即使被更宽的 read/write 覆盖时也始终生效。例如工作区可写但 .env 文件始终被拒绝。approvals_reviewer
谁来"看门"?
approvals_reviewer 决定谁负责审批 Codex 的操作请求。它控制的是 on-request 策略下触发的审批提示由谁来审。
两种模式
# 由人类审批(默认,顶层键)
approvals_reviewer = "user"
# 由 AI 自动审批(审核子代理)
approvals_reviewer = "auto_review"
auto_review 的风险
- AI 自行判断命令是否安全
- 可能存在"AI 误判"
- 建议只在 read-only 沙箱下用
[apps.<name>] 覆盖
为特定工具定制规则
为不同的 App / MCP 连接器指定不同的工具审批和启用规则。apps 段控制的是连接器工具调用,不是 shell 命令。
# 默认所有 App 的行为
[apps._default]
enabled = true # 默认启用所有 App 工具
destructive_enabled = false # 带破坏性提示的工具默认需审批
open_world_enabled = false # 带开放世界提示的工具默认需审批
# 特定 App 覆盖(如 GitHub 连接器)
[apps.github]
default_tools_enabled = true
default_tools_approval_mode = "auto" # 自动放行该 App 的工具调用
# 危险 App:始终需要审批
[apps.docker]
destructive_enabled = false
default_tools_approval_mode = "prompt" # 每次都弹确认
apps 段控制的是 MCP / 连接器工具调用的审批行为,不是 shell 命令。Shell 命令的审批由 approval_policy + sandbox_mode 控制。Config Profiles 机制
一套配置,多种场景
Profile 是 TOML 的"叠加层"。通过 -p <name> 加载 $CODEX_HOME/<name>.config.toml。
# 文件结构
$CODEX_HOME/
├── config.toml # 基础配置
├── work.config.toml
├── personal.config.toml
└── oss.config.toml
codex -p work # 加载 config.toml + work.config.toml
codex -p oss # 加载 config.toml + oss.config.toml
-p 叠加时,Profile 覆盖同名字段。Profile:work
工作项目 —— 适度防御
# $CODEX_HOME/work.config.toml
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = false # 断网
approval_policy = "on-request"
approvals_reviewer = "user" # 人工审批
Profile:personal
个人项目 —— 舒适高效
# $CODEX_HOME/personal.config.toml
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = true
writable_roots = ["/tmp", "/home/user/downloads"]
approval_policy = "on-request" # 沙箱内零打断
Profile:oss
开源 repo —— 只读审查
# $CODEX_HOME/oss.config.toml
sandbox_mode = "read-only"
approval_policy = "never"
实战:workspace-write + 网络
npm install 全流程
场景
让 Codex 初始化一个新的 Express 项目,需要 npm init、npm install。
# config.toml
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = true # npm install 需要网络
approval_policy = "on-request" # 沙箱内零打断,越界才确认
$ codex "帮我初始化一个 Express 项目"
> ✅ npm init -y (沙箱内 — 自动执行)
> ✅ npm install express (沙箱内 + 网络 — 自动执行)
> ✅ npm i -D typescript (沙箱内 + 网络 — 自动执行)
> ✅ npx tsc --init (沙箱内 — 自动执行)
实战:只读 + /review
绝对安全的审查
codex -s read-only
> 请 review src/auth.ts 的安全性
Codex 能做什么
- ✅ 读取
src/auth.ts及相关文件 - ✅ 分析安全漏洞并输出报告
- ❌ 修改任何文件(沙箱禁止)
- ❌ 上网搜索(read-only 默认断网)
为什么最安全
- Prompt 里写"修复它"也无效
- Prompt injection 无法破墙
- 审计日志清晰:只有读取
实战:多 Profile 切换
用 alias 管理场景
# ~/.zshrc or ~/.bashrc
alias codex-work='codex -p work'
alias codex-dev='codex -p personal'
alias codex-review='codex -s read-only -a never'
$ codex-work "写一个支付模块"
$ codex-dev "做个 side project 首页"
$ codex-review "review 这个 PR"
.codex/config.toml 中直接写差异配置,进入该项目目录时自动叠加生效(无需 -p 指定)。Profile 叠加规则
字段如何合并?
规则
- 标量:Profile 覆盖基础
- 数组:Profile 覆盖(不追加!)
- 表段:合并后覆盖同名字段
# config.toml (基础)
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = false
writable_roots = ["/tmp"]
# personal.config.toml (Profile)
[sandbox_workspace_write]
network_access = true
writable_roots = ["/tmp", "/home/user/downloads"]
# 最终生效:
# network_access = true ← Profile 覆盖
# writable_roots = ["/tmp", "/home/user/downloads"] ← 整个数组被替换
writable_roots 会替换整个基础数组,而不是在后面追加。实战:Profile 切换演示
同一任务,不同行为
| Profile | sandbox | approval | 运行 "git push" |
|---|---|---|---|
| work | workspace-write | on-request + 人工 | 弹出确认 ✅ |
| personal | workspace-write | on-request | 沙箱内自动 ✅ |
| oss | read-only | never | 沙箱拒绝 ❌ |
git push,三种命运。这就是 Profile 管理的价值所在。常见错误 1:沙箱审批冲突
on-request + danger-full-access
# 危险组合
sandbox_mode = "danger-full-access"
approval_policy = "on-request"
# 修复:用 workspace-write 保持边界
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = true
approval_policy = "on-request"
常见错误 2:忘开网络
npm install 突然失败
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = false # ← 问题所在
$ codex "安装依赖"
> Error: ECONNREFUSED registry.npmjs.org
network_access 默认为 false(网络默认关闭)。需要显式设为 true。# 修复
[sandbox_workspace_write]
network_access = true
常见错误 3:数组覆盖陷阱
Profile 丢了基础可写目录
# config.toml(基础)
[sandbox_workspace_write]
writable_roots = ["/tmp/data", "/cache"]
# work.config.toml(Profile)
[sandbox_workspace_write]
writable_roots = ["/tmp/work"] # 替换整个数组!
/tmp/data 和 /cache 不再可写。Profile 的数组替换而非追加基础数组。# 修复:完整列出所有需要的目录
# work.config.toml
[sandbox_workspace_write]
writable_roots = ["/tmp/data", "/cache", "/tmp/work"]
常见错误 4:reviewer 误用
AI 自己审自己
# 危险
sandbox_mode = "danger-full-access"
approval_policy = "on-request"
approvals_reviewer = "auto_review"
# 修复:高风险必须人工 + 保留沙箱
sandbox_mode = "workspace-write"
approval_policy = "on-request"
approvals_reviewer = "user"
常见错误 5:-p 顺序
多 Profile 层层叠加
# 可以接多个 profile
codex -p work -p personal # work 先加载,personal 后加载(后者优先)
加载顺序
- 加载全局
config.toml - 按顺序加载每个
-pProfile - 后面的 Profile 覆盖前面的同名字段
沙箱速查表
快速参考
| 你想… | CLI 参数 | config.toml |
|---|---|---|
| 只读审查 | -s read-only | sandbox_mode = "read-only" |
| 日常写代码 | 默认推荐 | sandbox_mode = "workspace-write" |
| 写系统文件 | -s danger-full-access | sandbox_mode = "danger-full-access" |
| 开启联网 | — | [sandbox_workspace_write] |
| 启动不加确认 | -a never | approval_policy = "never" |
审批策略速查
三种有效策略
| 策略 | 行为 | 最配沙箱 | 推荐度 |
|---|---|---|---|
never | 不弹确认 | read-only | ⭐⭐⭐ 审查/CI |
on-request | 越界才确认 | workspace-write | ⭐⭐⭐⭐⭐ 日常 |
untrusted | 每条确认 | danger-full-access | ⭐⭐ 高安全 |
on-failure 不再推荐。交互式用 on-request,非交互用 never。总结
给 Codex 一个边界
今天学到了什么
- 3 种沙箱模式:read-only / workspace-write / danger-full-access
- 3 种审批策略:never / on-request / untrusted(+ 弃用的 on-failure)
- CLI 运行时覆盖:
-s/-a/-m/-p - Config Profile 管理多场景
- approvals_reviewer + [apps] 细粒度控制
核心原则
- 沙箱越宽,审批越严
- Profile 用差异
- 数组覆盖需谨慎
- 高风险人工审