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 会拒绝访问,并且优先于同等具体度的 writeread。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 将主机模式映射为 allowdeny。如果没有任何 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_PROXYHTTPS_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)_PROXYALL_PROXY 设置来发起外连请求。
permissions.<name>.network.allow_local_binding Boolean false 设为 true 时关闭本地/私网保护。为 false 时,像 localhost127.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 条目使用 readwritedeny

Access Meaning
read 允许命令读取文件并列出该路径下的目录,但不能在这里创建、修改、重命名或删除文件。
write 允许命令读取和修改该路径下的文件,只要操作系统允许,也包括创建、重命名和删除文件。
deny 拒绝该路径下的读取和写入。用它从更宽泛的 readwrite 授权中切出不允许的子路径。

更具体的条目会覆盖更宽泛的条目。当两个条目指向同一路径时,deny 优先于 writewrite 优先于 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 规则使用。readwrite 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_modesandbox_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 使用 bubblewrapseccomp,并在兼容路径上提供 Landlock。最强的执行路径取决于 user namespaces 和内核支持;受限的容器主机可能会强制走兼容路径,不支持的 split policies 会被拒绝。
  • 在原生 Windows 上,elevated sandboxing 最强,因为它可以使用专用的低权限 sandbox 用户、filesystem 边界和防火墙规则。unelevated sandboxing 是弱一些的回退方案,网络隔离更弱,也无法强制执行所有拆分读写 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 和误连本地服务。要访问 localhost127.0.0.1,需要在 [permissions.<name>.network.domains] 里显式 allowlist;如果主机名会解析到本地或私网地址,还可能需要把 allow_local_binding = true 打开。