OpenAI Codex 的权限配置用来给本地命令设置最小权限边界,适合控制哪些目录可读写、哪些网络域名可访问。配置时不要把 default_permissions 和 [permissions] 与旧的 sandbox_mode / sandbox_workspace_write 混用;如果任何生效配置层里出现了 sandbox_mode,Codex 会优先使用旧沙箱设置。
OpenAI Codex 权限配置与报错排查
Beta 版本。Permission profiles 仍在积极开发中,行为和字段可能变化。
Permission profiles 用来限制 Codex 代你执行的本地命令访问哪些文件、哪些网络目标。它把两类规则组合在一个命名策略里:
- filesystem 规则:控制命令能读写什么路径
- network 规则:控制命令能连到哪些目的地
适合这些场景:
- 只想让 Codex 查看代码库,不让它改文件
- 只想让 Codex 在当前工作区内修改代码
- 想限制网络只访问少数域名
- 想把环境文件、密钥文件、敏感目录排除在外
本地 permission profiles 支持 macOS、Linux、WSL 和原生 Windows。平台差异和限制见 Security limitations。
如果你要配置 Codex cloud 的网络权限,见 Internet Access。
定义和选择 profile
Codex 内置了 3 个权限 profile:
:read-only:本地命令只读:workspace:允许在当前 workspace roots 内写入:danger-full-access:取消本地沙箱限制,只适合你明确需要广泛访问时使用
创建自定义 profile 时,在 [permissions.<name>] 下定义,然后把顶层 default_permissions 设为这个名字,或者设为内置值之一。
下面这个例子里,project-edit 是自定义 profile 名,不是内置值。
自定义 profile 里有两个相关概念:
[permissions.<name>.workspace_roots]:添加这个 profile 也认可的 workspace roots[permissions.<name>.filesystem.":workspace_roots"]:定义 Codex 对所有有效 workspace roots 应用的 filesystem 规则,包括当前会话的 runtime workspace roots 和 profile 里定义的 roots
profile 也遵循常规 config layer 模型。优先级更高的配置层可以在同名 profile 下追加或替换条目,不必重复声明整个 profile。
例如,组织级配置和用户级配置可以分别扩展同一个 profile:
# /etc/codex/config.toml
[permissions.server.workspace_roots]
"~/code/server" = true
# ~/.codex/config.toml
[permissions.server.workspace_roots]
"~/code/mobile-app" = true
当 server 生效时,这两个 workspace root 都会进入最终 profile。
default_permissions = "project-edit"
[permissions.project-edit.workspace_roots]
"~/code/app" = true
"~/code/shared-lib" = true
[permissions.project-edit.filesystem]
":minimal" = "read"
[permissions.project-edit.filesystem.":workspace_roots"]
"." = "write"
".devcontainer" = "read"
"**/*.env" = "deny"
[permissions.project-edit.network]
enabled = true
[permissions.project-edit.network.domains]
"api.openai.com" = "allow"
"objects.githubusercontent.com" = "allow"
"*.github.com" = "allow"
"tracking.example.com" = "deny"
这个 profile 的效果是:
- 读取常见开发工具需要的最小运行时路径
- 对当前会话和 profile 定义的 roots 应用同一套 workspace-root 规则
.devcontainer/在每个 root 下保持只读- 用 glob 规则拒绝匹配到的环境文件
- 只允许通过配置的域名策略访问网络
在激活的 profile 里,更窄的 deny 规则会继续生效,即使更宽泛的路径本来可读或可写。比如可以让 workspace roots 可写,同时把匹配到的 .env 路径设为 deny。
配置项
| Entry | Type / values | Default | Details |
|---|---|---|---|
default_permissions |
String profile name | None | 指定 Codex 默认应用的权限 profile。值必须匹配 [permissions] 下的某个 profile,或像 :workspace 这样的内置 profile。启用 permission profiles 时必须设置。若旧 sandbox 设置也处于生效状态,Codex 会改用旧沙箱设置。 |
[permissions.<name>] |
Table | None | 定义一个 profile 及其标识。default_permissions 会选择其中一个 profile 作为默认值;其他权限选择器也使用这个 profile 名称。 |
[permissions.<name>.workspace_roots] |
Table | None | 添加 profile 定义的 workspace roots,这些 roots 会和当前会话的 runtime workspace roots 一起应用 :workspace_roots filesystem 规则。 |
permissions.<name>.workspace_roots."<path>" |
Boolean | false |
当为 true 时,把该路径加入 profile 的 workspace root 集合。设为 false 的条目保持未启用。 |
[permissions.<name>.filesystem] |
Table | None | 将 filesystem 路径映射到访问值或带范围的子路径映射。缺失或为空的 filesystem 表会保持文件系统访问受限,并在启动时发出警告。 |
permissions.<name>.filesystem.glob_scan_max_depth |
Number | None | 在 Linux、WSL 和原生 Windows 上,Codex 在 sandbox 启动前会对 deny-read glob 做匹配快照。这个值限制该展开深度。值越大,启动前扫描工作越多。若使用无界 ** 模式并需要有限预展开,至少设为 1。 |
[permissions.<name>.filesystem]."<path>" |
read, write, or deny |
None | 为受支持路径授予直接访问。deny 会拒绝访问,并且优先于同等具体度的 write 或 read。Codex 会拒绝当前运行时无法强制执行的直接写入规则。 |
[permissions.<name>.filesystem."<path>"]."<subpath>" |
read, write, or deny |
None | 授予 <path> 下某个后代路径的访问权限。基路径用 . 表示。其他子路径必须是相对后代,不能包含 . 或 .. 组件。 |
[permissions.<name>.network] |
Table | None | 为该 profile 配置网络沙箱代理和网络策略。 |
permissions.<name>.network.enabled |
Boolean | false |
为该 profile 启用 sandboxed commands 的网络访问。这会改变沙箱网络策略,但不会单独启动网络代理。 |
[permissions.<name>.network.domains] |
Table | None | 将主机模式映射为 allow 或 deny。如果没有任何 allow 条目,域名请求会被阻止。deny 条目会覆盖 allow 条目。 |
permissions.<name>.network.domains."<pattern>" |
allow or deny |
None | 支持精确主机、*.example.com 表示仅子域、**.example.com 表示根域和子域,以及 * 作为仅允许使用的全局通配符。主机模式会经过裁剪空白、转小写、去掉尾随点,以及去掉简单端口或方括号的归一化处理。 |
[permissions.<name>.network.unix_sockets] |
Table | None | 映射 Unix socket allowlist 覆盖项。只应用于 Docker 这类本地集成。 |
permissions.<name>.network.unix_sockets."<path>" |
allow or none |
None | 用 allow 把绝对 Unix socket 路径加入最终 allowlist,或用 none 清除从低优先级配置层继承来的允许项。none 不是单独的 deny 列表决策。 |
permissions.<name>.network.proxy_url |
URL string | http://127.0.0.1:3128 |
HTTP proxy listener,用于 HTTP_PROXY、HTTPS_PROXY、websocket proxy 变量和相关工具的 proxy 环境变量。 |
permissions.<name>.network.enable_socks5 |
Boolean | true |
启用 ALL_PROXY 和 FTP proxy 变量使用的 SOCKS5 listener。 |
permissions.<name>.network.socks_url |
URL string | http://127.0.0.1:8081 |
SOCKS5 listener 地址。 |
permissions.<name>.network.enable_socks5_udp |
Boolean | true |
在启用 SOCKS5 listener 时,开启 SOCKS5 UDP 支持。 |
permissions.<name>.network.allow_upstream_proxy |
Boolean | true |
允许 network sandbox proxy 遵守上游 HTTP(S)_PROXY 和 ALL_PROXY 设置来发起外连请求。 |
permissions.<name>.network.allow_local_binding |
Boolean | false |
设为 true 时关闭本地/私网保护。为 false 时,像 localhost 或 127.0.0.1 这样的精确本地字面量必须显式加入 allowlist,而解析到本地或私网 IP 的主机名仍会被阻止。 |
permissions.<name>.network.dangerously_allow_non_loopback_proxy |
Boolean | false |
允许代理监听器绑定非 loopback 地址。普通本地开发不要启用。 |
permissions.<name>.network.dangerously_allow_all_unix_sockets |
Boolean | false |
绕过 Unix socket allowlist。仅在支持 Unix socket 代理的场景下有效,这是一个很宽的本地逃逸口子。 |
Filesystem permissions
Filesystem 条目使用 read、write 或 deny。
| Access | Meaning |
|---|---|
read |
允许命令读取文件并列出该路径下的目录,但不能在这里创建、修改、重命名或删除文件。 |
write |
允许命令读取和修改该路径下的文件,只要操作系统允许,也包括创建、重命名和删除文件。 |
deny |
拒绝该路径下的读取和写入。用它从更宽泛的 read 或 write 授权中切出不允许的子路径。 |
更具体的条目会覆盖更宽泛的条目。当两个条目指向同一路径时,deny 优先于 write,write 优先于 read。
这个优先级让 profile 可以先描述一个大的工作区域,再把某些文件或目录切成不可读:
[permissions.project-edit.filesystem]
":minimal" = "read"
[permissions.project-edit.filesystem.":workspace_roots"]
"." = "write"
".devcontainer" = "read"
"**/*.env" = "deny"
在这个例子里,workspace root 保持可写,.devcontainer/ 保持可读但不可写,匹配到的环境文件对 sandboxed commands 不可用。
更具体的路径也可以在更宽泛的 deny 里重新打开更窄的子树:
[permissions.project-edit.filesystem]
"~/Documents" = "deny"
"~/Documents/codex" = "write"
支持的路径形式:
| Path | Meaning | Scoped subpaths |
|---|---|---|
:root |
文件系统根目录 | 仅 . |
:minimal |
常见工具所需的平台和运行时路径 | 仅 . |
:workspace_roots |
当前会话的 workspace roots,加上任何已启用的 profile-defined workspace roots | 支持 |
:tmpdir |
可用时的 $TMPDIR 位置 |
仅 . |
/absolute/path |
平台绝对路径,例如 macOS/Linux/WSL 上的 /path,或原生 Windows 上的 C:\path |
支持 |
~/path |
当前用户 home 目录下的路径 | 支持 |
在原生 Windows 上,home-relative 路径也可以使用反斜杠,例如 ~\work。
只有在 profile 明确需要较宽的读覆盖时,才使用 :root:
[permissions.audit.filesystem]
":root" = "read"
当你想把 access 范围限定到每个 workspace root 内部的子路径时,可以在 :workspace_roots 下使用嵌套条目:
[permissions.project-edit.filesystem.":workspace_roots"]
"." = "write" # each workspace root
"docs" = "read" # each workspace-root docs directory
"generated" = "deny" # each workspace-root generated directory
嵌套子路径必须保留在各自的 workspace root 内。像 ../other-repo 这样的父级穿越会被拒绝。
为什么 exact path 或 glob 的 deny 读规则会更安全
如果某些文件不该让 Codex 读取,即使附近的更宽泛规则已经授权,也应使用 deny。精确路径适合固定位置,比如 ~/.ssh。如果敏感文件位置会随仓库变化,glob 模式更合适。
当 glob 位于 :workspace_roots 下时,Codex 会把它理解为相对于每个有效 workspace root 的路径。例如:
[permissions.project-edit.filesystem.":workspace_roots"]
"**/*.env" = "deny"
这条规则会拒绝读取每个 runtime 或 profile-defined workspace root 下匹配到的 .env 文件。适合保留正常 workspace 写入,同时让环境文件、生成的密钥或类似凭据文件保持不可读。
deny glob 模式支持作为 deny-read 规则使用。read 或 write glob 在 Linux、WSL 和原生 Windows 的 sandboxing 上兼容性较差,因此能用精确路径或子树规则时,优先写成 "docs/**" = "read" 这类形式。
在 Linux、WSL 和原生 Windows 上,无界 ** deny-read 模式在 sandbox 启动前可能需要做有界预展开。像 "**/*.env" = "deny" 这样的规则,需要设置 glob_scan_max_depth:
[permissions.project-edit.filesystem]
glob_scan_max_depth = 3
[permissions.project-edit.filesystem.":workspace_roots"]
"**/*.env" = "deny"
glob_scan_max_depth 至少要为 1。值越高,sandbox 启动前扫描越深,在 Linux、WSL 和原生 Windows 上会增加启动工作量。如果你不想用有界展开,可以显式列出深度,例如 *.env、*/*.env、*/*/*.env。
如果同一套规则要作用到除了当前会话 root 之外的更多 workspace roots,可以把可复用 roots 加到 profile 里:
[permissions.project-edit.workspace_roots]
"~/code/app" = true
"~/code/shared-lib" = true
当该 profile 生效时,Codex 会把 :workspace_roots 规则同时应用到当前会话的 runtime workspace roots,以及每个已启用的 profile-defined workspace root。
在原生 Windows 上,像 D:\work 这样的盘符路径,以及像 \\server\share 这样的 UNC 路径,都支持作为绝对路径。
Network permissions
把 enabled = true 打开后,所选 profile 才允许网络访问:
[permissions.project-edit.network]
enabled = true
当网络访问启用时,Codex 默认使用完整网络行为。多数 profile 还应定义域名规则:
[permissions.project-edit.network.domains]
"example.com" = "allow" # exact host
"*.example.com" = "allow" # subdomains only
"**.example.com" = "allow" # apex and subdomains
"ads.example.com" = "deny" # deny wins over allow
网络 sandbox proxy 默认绑定到本地监听地址:
[permissions.project-edit.network]
enabled = true
proxy_url = "http://127.0.0.1:3128"
enable_socks5 = true
socks_url = "http://127.0.0.1:8081"
enable_socks5_udp = true
除非你是在对接特定 runtime,否则保持这些监听设置为默认值即可。dangerously_* 网络键是专门留给特殊环境的逃生口,普通本地开发不建议使用。
本地和私网为什么会被拦截
Codex 默认会应用本地/私网保护,防止 DNS rebinding 和误连本地服务。若你要有意允许某个本地目标,需要把精确主机名或 IP 字面量加入 allowlist:
[permissions.project-edit.network.domains]
"localhost" = "allow"
"127.0.0.1" = "allow"
只有当 profile 必须访问会解析到本地或私网地址的已允许主机名时,才把 allow_local_binding = true 打开:
[permissions.project-edit.network]
enabled = true
allow_local_binding = true
[permissions.project-edit.network.domains]
"localhost" = "allow"
Unix sockets 怎么配置
Unix socket 代理适合 Docker 这类本地集成,使用时要尽量克制:
[permissions.project-edit.network.unix_sockets]
"/var/run/docker.sock" = "allow"
"/tmp/old.sock" = "none"
用 none 可以清除从低优先级配置层继承来的 socket 允许项。它不是一种单独的 domain-style deny 规则。
启用 Unix sockets 时,proxy listeners 仍应绑定到 loopback 地址。
从旧 sandbox 设置迁移
当你想用一个可复用 profile 同时描述 filesystem 和 network 行为时,permission profiles 可以替代旧的 sandbox_mode 和 sandbox_workspace_write 组合。一次会话里只能用一种系统,不能同时混用。
建议的起点:
- 只读工作流:用内置
:read-only,或者自定义一个只给必要读权限的 profile - workspace 编辑:用内置
:workspace,或者自定义一个通过:workspace_roots写入、再额外开放所需临时目录或缓存路径的 profile - 不受限本地执行:只有在你确实想要最宽本地访问模型时才用
:danger-full-access
profiles 描述的是会话的本地默认姿态。组织管理的要求仍然可以继续施加限制,用户配置不能把它们放宽。见 Managed configuration,了解管理员强制执行的 filesystem 和 network 限制。
Scope and enforcement
Permission profiles 定义的是本地 sandboxed command execution 的边界。它们要和 approval policy,以及 Codex 其他 surface 的独立控制一起使用。
profile 控制什么
- 本地命令执行: Permission profiles 管理在你机器上运行的 sandboxed commands。App connectors、MCP servers、browser 或 computer-use surfaces、Codex cloud environment settings,以及已批准的提权,都会使用各自的控制。
- Filesystem writes: 有写权限的 profile 可以创建持久化变更。写到脚本、构建步骤、包管理器 hook、shell 启动文件和共享目录时要特别小心,因为后续工具或用户可能会在原始 sandbox 之外执行这些文件。
- Outbound destinations: 网络域名规则只约束 sandboxed command 流量可以通过 network proxy 去哪里,不判断目标是否可信;而且通配允许规则的范围始终很大。
- Local services: 本地和私网目标默认会被阻止。只有显式允许
localhost、私网 IP、Unix sockets,或者把allow_local_binding = true打开,才会放行本地服务。
enforcement 怎么工作
- 在 macOS 上,Codex 使用 Seatbelt sandbox profiles。如果选定策略无法被平台 sandbox 强制执行,Codex 会直接拒绝运行该命令,而不是悄悄无沙箱执行。
- 在 Linux 和 WSL 上,Codex 使用 bubblewrap 和 seccomp,并在兼容路径上提供 Landlock。最强的执行路径取决于 user namespaces 和内核支持;受限的容器主机可能会强制走兼容路径,不支持的 split policies 会被拒绝。
- 在原生 Windows 上,
elevatedsandboxing 最强,因为它可以使用专用的低权限 sandbox 用户、filesystem 边界和防火墙规则。unelevatedsandboxing 是弱一些的回退方案,网络隔离更弱,也无法强制执行所有拆分读写 carveout,因此不支持的策略会被拒绝。需要 Linux 沙箱模型时,请用 WSL。
操作建议
给任务选择尽可能窄、但仍能完成工作的 profile,尤其是在你开放写入或出站网络访问时。让 approval policy、secret 处理和 allow 规则都和这个权限级别保持一致。
常用 profile 示例
只读并允许少量网络
default_permissions = "readonly-net"
[permissions.readonly-net.filesystem]
":minimal" = "read"
[permissions.readonly-net.filesystem.":workspace_roots"]
"." = "read"
[permissions.readonly-net.network]
enabled = true
[permissions.readonly-net.network.domains]
"api.openai.com" = "allow"
workspace 可写但不联网
default_permissions = "project-edit"
[permissions.project-edit.filesystem]
":minimal" = "read"
[permissions.project-edit.filesystem.":workspace_roots"]
"." = "write"
[permissions.project-edit.network]
enabled = false
workspace 可写并允许公开 Web 访问
default_permissions = "workspace-net"
[permissions.workspace-net.filesystem]
":minimal" = "read"
[permissions.workspace-net.filesystem.":workspace_roots"]
"." = "write"
[permissions.workspace-net.network]
enabled = true
[permissions.workspace-net.network.domains]
"*" = "allow"
只有在你确实要放行公共网络访问时,才使用全局 "*" allow 规则。更宽的 allowlist 仍然可以再用 deny 规则收窄。
常见问题
OpenAI Codex 的 default_permissions 和旧 sandbox_mode 能一起用吗
不能。default_permissions / [permissions] 和旧的 sandbox_mode / sandbox_workspace_write 不能混用。只要任何生效配置层里出现了 sandbox_mode,或者你通过 --sandbox 指定了旧模式,Codex 就会使用旧沙箱设置。
OpenAI Codex 怎么只让它读项目,不让它改文件
把 default_permissions 设为 :read-only,或者自定义一个只给 read 权限的 profile。只读 profile 里 filesystem 只能读,不能创建、修改、重命名或删除文件。
OpenAI Codex 为什么访问 localhost 还是被拦截
Codex 默认会阻止本地和私网目标,防止 DNS rebinding 和误连本地服务。要访问 localhost 或 127.0.0.1,需要在 [permissions.<name>.network.domains] 里显式 allowlist;如果主机名会解析到本地或私网地址,还可能需要把 allow_local_binding = true 打开。