全部 Agent 工程

规范文件

Codex 沙箱、审批与命令网络:三个开关怎样组合核对

分清 sandbox_mode、approval_policy 与 network_proxy,并用离线脚本演算域名规则的匹配结果。

AI Nav City撰写 / 更新

Codex 对命令的约束由两层组成:沙箱模式决定命令技术上能写哪里、能不能联网,审批策略决定什么时候必须先问你。想按域名放行网络,还要再打开 network_proxy。三者相互独立,最容易出的错是以为打开 network_proxy 就等于允许联网,或者以为写了域名规则就一定被执行。本文依据官方文档整理一张组合核对表和一个域名规则演算脚本,没有启动 Codex,没有放行或访问任何网络,演算结果不能代替真实产品的行为。

核验日期
· 未实测
适用于
  • Codex 适用于 Codex CLI、IDE 扩展与桌面应用的本机命令;官方页面没有统一版本门槛,托管环境另有管理员要求。[1]
涉及工具

文件位置

路径适用范围读取方式
~/.codex/config.toml用户级 approval_policy、sandbox_mode、网络与代理设置。Codex 启动时读取;优先级低于命令行标志、受信项目配置和选中的 profile。[2]
./.codex/config.toml项目级覆盖,只在你信任该项目时加载。从项目根到当前目录逐级生效,离当前目录近的优先。[2]

什么时候用

  • 需要确认命令能否联网、联网时按哪些域名约束,或审批提示出现的原因。[1]

什么时候不用

  • 需要约束网页搜索、MCP 连接或模型请求,这些不经过命令网络代理。[1]

先分清两层:沙箱与审批

  • 沙箱模式(sandbox_mode)决定命令在技术上能做什么;审批策略(approval_policy)决定什么时候必须先问你。
  • Codex CLI 与 IDE 扩展默认无网络,写权限限于当前工作区;工作区包含当前目录和 /tmp 之类的临时目录,可用 /status 查看。
  • Auto 预设(workspace-write 加 on-request)下,工作区内的读写和命令自动进行;编辑工作区外的文件或运行需要联网的命令,会先请求批准。
  • workspace-write 下,可写根目录里的 .git、.agents、.codex、.aws(为目录时)仍是只读,保护对其下所有内容递归生效。
  • 官方已停用 approval_policy = "untrusted",留在用户或项目配置、profile、启动脚本或托管默认里,可能让客户端无法启动,需要删除并改用官方迁移段落给出的写法。

[1]

联网开关与 network_proxy 的组合

官方说明 network_proxy 只改变「已开启的网络访问如何被约束」,本身不授予网络访问;只写域名规则也不会启用代理。domains 未设置时采用 allowlist 行为,也就是没有任何外部目的地被允许,直到你写入 allow 规则。[1]

表:命令网络与 network_proxy 的组合(依据官方说明)
sandbox_workspace_write.network_accessfeatures.network_proxy.enabled官方说明的结果
关闭(默认)开启网络仍关闭,代理功能不起作用
开启关闭或未设置网络开启,出站不受限,直接访问
开启开启网络开启,出站受你配置的网络策略约束

[1]

下面是一份原创配置样例:启用命令联网,再用代理把出站限制在 **.example.org 之内并单独拒绝 ads.example.org。我只用 Python 的 tomllib 解析确认语法有效,Codex 没有读取过它。[1]

示例:原创配置样例;仅解析了 TOML 语法,未让 Codex 读取
approval_policy = "on-request"
sandbox_mode = "workspace-write"

[sandbox_workspace_write]
network_access = true

[features.network_proxy]
enabled = true
domains = { "**.example.org" = "allow", "ads.example.org" = "deny" }

[1]

域名规则怎么匹配,以及演算脚本

  • 精确主机名只匹配自身。
  • *.example.com 匹配 api.example.com 这样的子域名,但不匹配 example.com 本身。
  • **.example.com 同时匹配根域名和子域名。
  • 单独的 * 是全局 allow,匹配任何未被拒绝的公共主机,官方建议按需使用范围更窄的规则,且 * 只允许出现在 allow 规则里。
  • deny 永远优先于 allow。

[1]

下面的脚本只实现上面这些匹配规则和三种开关组合,并带有 8 条断言。它不判断「公共主机」,也不模拟 DNS 与私有地址检查,所以结果只适合在写规则前用来核对通配符的覆盖范围。[1]

示例:原创演算脚本;离线运行,不是 Codex 的网络代理
import assert from "node:assert/strict";

const match = (rule, host) => {
  if (rule === "*") return true; // docs: any public host; the public check is not simulated
  if (rule.startsWith("**.")) return host === rule.slice(3) || host.endsWith(rule.slice(2));
  if (rule.startsWith("*.")) return host.endsWith(rule.slice(1));
  return host === rule;
};

export function decide({ networkAccess, proxy, domains = {} }, host) {
  if (!networkAccess) return "blocked: command network is off";
  if (!proxy) return "allowed: direct, domain rules not enforced";
  const hit = want => Object.entries(domains).some(([rule, v]) => v === want && match(rule, host));
  if (hit("deny")) return "blocked: deny rule";
  if (hit("allow")) return "allowed: allow rule";
  return "blocked: no allow rule";
}

const domains = { "api.openai.com": "allow", "*.example.com": "allow", "evil.example.com": "deny" };
const on = { networkAccess: true, proxy: true, domains };
assert.match(decide({ networkAccess: false, proxy: true, domains }, "api.openai.com"), /^blocked/);
assert.match(decide({ networkAccess: true, proxy: false, domains }, "anything.test"), /^allowed: direct/);
assert.match(decide(on, "api.openai.com"), /^allowed/);
assert.match(decide(on, "a.example.com"), /^allowed/);
assert.match(decide(on, "example.com"), /^blocked/); // *.example.com excludes the apex
assert.match(decide(on, "evil.example.com"), /^blocked: deny/); // deny wins
assert.match(decide({ ...on, domains: { "**.example.com": "allow" } }, "example.com"), /^allowed/);
assert.match(decide({ ...on, domains: {} }, "api.openai.com"), /^blocked: no allow/);
console.log("net policy model: all assertions passed");

[1]

表:对上面配置样例规则的演算结果(脚本模型,不是 Codex 输出)
主机演算结果原因
example.org放行**.example.org 同时匹配根域名
docs.example.org放行子域名命中 allow 规则
ads.example.org拒绝deny 优先于 allow
other.test拒绝没有匹配的 allow 规则

[1]

代理管不到的地方

  • 官方说明:命令网络代理过滤的是本地命令沙箱里的脚本、程序和子进程;它不过滤网页搜索、app 或 connector 工具调用、MCP 服务器连接、浏览器或 Computer Use 活动、云端任务,也不过滤客户端自己的模型与认证请求。
  • 默认 allow_local_binding = false,会拦截环回、链路本地和私有网络目的地;解析到私有地址的主机名即使命中 allow 规则也保持被拦截。官方说明 DNS 与 IP 分类检查只能降低 DNS rebinding 风险,不能消除。
  • 在受管环境里,管理员的网络要求单独配置;官方提醒要同时测试普通命令和被批准的沙箱升级,因为获批的完整沙箱升级可能绕过命令代理。
  • 脚本不模拟以上任何一项;网页搜索另有 web_search 设置,默认读缓存,不属于命令网络。

[1]

配置优先级与本文范围

官方列出的取值顺序(从高到低)是:命令行标志与 -c 覆盖、受信项目的 .codex/config.toml、--profile 选中的 profile、用户 ~/.codex/config.toml、云托管默认、系统配置、内置默认,所以一次性的 -c 覆盖会盖住文件里的值;管理员的 requirements.toml 还可以禁止 approval_policy = "never" 之类的值。发现网络与预期不符时,先用 /status 与启动参数确认实际生效的值,再改规则。本文只核验官方说明,没有启动 Codex、没有放行任何域名、没有联网,也不认证任何套餐或额度。[1][2]

来源

以下均为官方页面,核验日期见各条;链接指向核验时的版本。

  1. OpenAI · Agent approvals & security
  2. OpenAI · Config basics

发现错误?告诉我们 →