Codex 沙箱里的命令连不上网:先搞清是哪个开关关的
现象长什么样
Codex(OpenAI Codex)在沙箱里执行你交给它的命令,某些命令需要出网——装依赖、拉取远程资源、访问本机起的服务。你会看到的现象通常是:同一条命令,你自己在终端里跑没问题,交给 Codex 在沙箱里跑就连不上;或者昨天还好好的,今天换了个目录、换了个权限档就不通了。
这类问题最容易走的弯路,是一头扎进系统防火墙、DNS、公司代理里排查半天,最后发现是 config.toml 里一个布尔值。Codex 的出网能力不是一个开关,而是层层叠加的若干个开关,任何一层关掉,下面几层配得再对也没用。所以排查顺序比排查手段重要。
下面这四层,按从粗到细的顺序排。
第 0 步:先把「版本」和「配置到底加载了没有」钉死
这一步跳过去,后面全是白排。
先确认版本。同一台机器上,我们采集事实时开头执行 codex --version 得到的是 codex-cli 0.131.0,十几分钟后再执行同一条命令得到的是 codex-cli 0.147.0,而 which -a codex 全程只有一个可执行文件。Codex 有自更新能力(check_for_update_on_startup 默认为 true),所以「我昨天看到的版本号」不能当依据,任何和版本相关的判断都要以当次输出为准:
codex --version
然后是更关键的一条:你改的配置,Codex 到底加载成功没有。
codex doctor --summary
在 codex-cli 0.147.0(Windows 11)上,doctor 的输出按 Notes / Environment / Configuration / Updates / Connectivity 等分组。我们故意用 codex -c 'features=[unclosed' doctor --summary 传入一段语法不合法的 TOML,结果是:命令没有崩溃退出,doctor 照常跑完,但 Notes 区出现了这么一条:
✗ config config could not be loaded - Fix the reported config error, then rerun codex doctor.
这条一手结论价值很大:配置文件写坏了,Codex 不会拦着你,它只是不加载。你以为自己把 network_access 打开了,实际上整份 config.toml 根本没生效。所以「改完配置没生效」的第一个动作永远是跑一次 doctor,看输出里有没有这条 ✗ config。
再看 Configuration 组的 sandbox 行。本机在 codex-cli 0.147.0(Windows 11)上显示的是:
sandbox restricted fs + restricted network · approval OnRequest
restricted network 就是明牌告诉你:当前这套配置下,沙箱的网络是受限状态。如果你看到的也是这个,那接下来四层就是要找出到底是谁把它限住的。
开关一:sandbox_mode —— 你可能压根不在能出网的那个模式里
三种沙箱模式(read-only / workspace-write / danger-full-access)的完整释义有专门篇目在讲,这里不整表照搬,只取跟「出网」直接相关的两行官方原文——因为出网这件事,真正有分歧的只有这两档:
workspace-write(官方标注这是默认模式):「The agent can read files, edit within the workspace, and run routine local commands inside that boundary.」命令是在这条边界内跑的,能不能出网要由后面几层开关决定,所以需要逐层排查的正是这一档。danger-full-access:「The agent runs without sandbox restrictions. This removes the filesystem and network boundaries…」文件系统和网络边界都撤掉了,如果你已经在这一档还连不上网,那问题一定不在 Codex 这边(见文末最后一节)。
至于 read-only,官方释义里写明了不经审批连命令都跑不起来,你遇到的多半不是「网络不通」而是「命令根本没执行」,不在本篇的排查范围内。
CLI 侧用 -s, --sandbox 指定,配置侧是 sandbox_mode。想确认取值有没有写错,故意传个非法值最快——在 codex-cli 0.147.0(Windows 11)上执行 codex -s bogus-mode,得到的是:
error: invalid value 'bogus-mode' for '--sandbox <SANDBOX_MODE>'
[possible values: read-only, workspace-write, danger-full-access]
这三个值就是全部合法取值,没有第四个。
这里必须提醒一个高频误解:approval_policy = "never" 不等于「放开权限」。never 的官方释义是「从不询问,执行失败直接回传给模型」,它改变的只是「要不要问你」,沙箱边界一寸没动。所以指望把审批策略调成 never 来解决连不上网,方向就是错的——你只会把「弹窗问你」变成「静默失败」,排查反而更难。真正撤掉边界的是 danger-full-access 或 --dangerously-bypass-approvals-and-sandbox(官方对后者的原文是「EXTREMELY DANGEROUS. Intended solely for running in environments that are externally sandboxed」)。
开关二:sandbox_workspace_write.network_access
确认在 workspace-write 之后,这是最直接的一个开关:
| 键 | 类型 | 说明 |
|---|---|---|
sandbox_workspace_write.network_access | boolean | workspace-write 沙箱内是否允许出网 |
官方文档没有给这个键的默认值,所以我这里也不替它写一个默认值——你应该去自己的 config.toml 里确认它到底有没有被显式设置过。
想快速验证「是不是它在拦」,不必改文件,用 -c 临时覆盖跑一次就行。-c 的行为在 codex-cli 0.147.0 上是明确的:点号路径表示嵌套,值按 TOML 解析,解析失败则按字面字符串处理:
codex -c sandbox_workspace_write.network_access=true doctor --summary
注意最后一句「解析失败按字面字符串处理」——这意味着你要是写成 network_access=ture(拼错),它不会报错,而是把 ture 当成一个字符串塞进去。这也是为什么改完要回头看 doctor 那一行,而不是看命令有没有报错。
开关三:权限档里的 network.* —— 域名级的那一层
前两层都对了还不通,往下就是权限档(permissions profile)。这一层管的是更细的粒度:不是「能不能上网」,而是「能上哪些网」。
| 键 | 说明 |
|---|---|
default_permissions | 沙箱化工具的默认权限档名 |
permissions.<name>.extends | 父档::read-only、:workspace 或某个命名档 |
permissions.<name>.network.enabled | 该档是否允许联网 |
permissions.<name>.network.mode | limited 或 full |
permissions.<name>.network.domains.<pattern> | allow 或 deny,支持精确主机与通配 |
permissions.<name>.network.allow_local_binding | 是否放开本地/内网访问 |
permissions.<name>.network.unix_sockets.<path> | allow 或 deny |
permissions.<name>.network.proxy_url / socks_url | 代理监听地址 |
排查时要盯住三处。
第一处是 network.mode。取值只有 limited 和 full 两个。落在 limited 上时,「能不能出网」就没有统一答案了,得看 domains 里的具体条目——这是最容易误判的地方:你测 A 站点通就以为网络开着,结果 B 站点在 deny 名单里。
第二处是 extends。权限档是可以继承的,父档写着 :read-only 而你只在子档里加了几条 allow 域名,那结果未必是你以为的样子。排查时把整条继承链摊开看,别只看你改的那一档。
第三处是 allow_local_binding。「沙箱里的命令连不上我本机起的服务」和「连不上外网」是两个问题,前者对应的是这个键,别混着排。
CLI 侧用 -P, --permission-profile <NAME> 指定权限档,codex sandbox 子命令也支持这个选项。想单独验证某个权限档的行为,可以直接用 codex sandbox 跑一条无害命令:
codex sandbox -P <你的权限档名> <一条无害的探测命令>
这条具体命令我们没有在本机跑过,输出以你自己机器为准。但我们跑过另外两条,结论可以直接用:
其一,在 codex-cli 0.147.0(Windows 11)默认沙箱状态下,用 codex sandbox 执行一条往仓库路径写文件的命令,命令返回之后目标文件并不存在。这说明沙箱确实在生效、并且失败可以是静默的——命令看起来跑完了,效果没落地。排查网络时请假定同样的事会发生:不要以「命令没报错」作为「网通了」的证据。
其二,--sandbox-state-* 这一组选项是绑在一起的。单独给 --sandbox-state-disable-network 而不给 --sandbox-state-json,会直接报参数缺失:
error: the following required arguments were not provided:
--sandbox-state-json <JSON>
也就是说,--sandbox-state-disable-network(禁用传入沙箱状态的直连网络)是在一份已有的 state JSON 之上做增删的,必须先有 --sandbox-state-json。如果你或者某个脚本在调 codex sandbox 时带了这个选项,那沙箱里没网就是你自己要求的,不是故障。
开关四:Windows 原生沙箱的权限模式
前三层是跨平台的,这一层只有 Windows 有,而且是中文用户踩得最多的一层。
先把平台差异说清楚,因为把 Linux 的排查步骤套到 Windows 上是纯浪费时间:
- macOS 用系统内置的 Seatbelt 框架
- Windows 在 PowerShell 中使用原生 Windows 沙箱,不需要 WSL、不需要虚拟机;在 WSL2 里则走 Linux 那套实现
- Linux / WSL2 需要用包管理器装
bubblewrap(bwrap)
Windows 原生沙箱有两种权限模式,由 windows.sandbox 控制:
| 模式 | 特征 |
|---|---|
elevated(官方标注为首选) | 使用专用的低权限沙箱用户;文件系统权限边界 + 防火墙规则;需要管理员批准的初始化设置 |
unelevated(回退) | 用「从当前用户派生的受限 Windows token」运行命令;基于 ACL 的文件系统边界;用环境级离线控制替代防火墙规则;官方明说保护更弱,但在拿不到管理员批准时可用 |
注意两种模式实现网络边界的机制根本不是一回事:elevated 靠防火墙规则,unelevated 靠环境级的离线控制。这直接导致一个后果——官方文档明确写了:某些任务会故意在无出网的状态下运行,取决于权限模式。换句话说,你在 unelevated 下遇到的「没网」有可能是设计如此,而不是配置写错了。这一条不搞清楚,你可以在 config.toml 里改到天亮也没用。
本机在 codex-cli 0.147.0(Windows 11)上,config.toml 里是 [windows] sandbox = "elevated",~/.codex/ 下确实存在 .sandbox/、.sandbox-bin/、.sandbox-secrets/ 三个目录。相关的还有 windows.sandbox_private_desktop(默认 true,默认在私有桌面上运行沙箱子进程)。
Windows 侧还有几条官方给的硬信息,排查时对照着看:
- 硬性要求:
winget必须可用。 - 版本支持:Windows 11 推荐;较新的 Windows 10(v1809+)为尽力而为(best effort);更老的 Windows 10 不推荐。
- 错误 1385,官方原文是「Windows is denying the logon type the sandbox user needs.」——含义是沙箱用户已经建好了,但策略不允许它执行命令。这不是网络问题,是沙箱压根没起来。
- 如果某个目录是「writable by Everyone」(对所有人可写),Codex 会告警,提示 Windows 权限过宽。这也和出网无关,别被它带偏。
- 初始化失败的常见原因:拒绝了 UAC 提示、本地用户创建被阻止、防火墙规则被限制。第三条和网络直接相关。
官方给的排查顺序只有四步,我照抄,不额外补注册表或组策略的改法(官方没给,我们也没验证过):① 重启 Codex ② 重试 elevated 初始化 ③ 需要时回退到 unelevated ④ 需要时发送诊断,日志位于 CODEX_HOME/.sandbox/sandbox.log。
第三步要提醒一句:回退到 unelevated 是「拿不到管理员批准时的可用选项」,不是「更好的选择」,官方对它的表述是保护更弱。别为了图省事默认就退到这一档。
还有两个开关不在你的 config.toml 里
一个在组织侧。 对 ChatGPT Work(web),官方文档给的路径是 Settings > Data controls > Work network access;关掉之后,命令只能访问必需主机名的允许列表。这部分我们没有实测,是官方文档口径。它的排查价值在于:如果你是企业环境、而且本地四层怎么查都正常,那就该去问管理员了,继续在本机翻配置是死路。
另一个带 experimental 标签。 更细的域名级控制除了走权限档,还有一条路是 features.network_proxy,它可以是布尔也可以是表,默认 false。请注意这个特性在 codex-cli 0.147.0 上,codex features list 里显示的阶段是 experimental、当前生效值 false。experimental 的东西不适合作为线上环境的排查结论或长期方案,知道有这么个东西、并确认它当前是关的就够了。想自己看一眼:
codex features list
改完怎么验证
按这个顺序验,每一步都是只读的,不会把机器搞乱:
codex doctor --summary,先看 Notes 区里有没有✗ config config could not be loaded。有这条就说明配置压根没加载,后面全都是幻觉。- 看 Configuration 组里的
sandbox行。本机在 codex-cli 0.147.0(Windows 11)上是restricted fs + restricted network · approval OnRequest——这一行是本机唯一能自查沙箱现状的只读入口,改动前后各跑一次做对照。至于它会不会随你的改动而变、变成什么样,我们没有做过前后对照的实测,别把它当成唯一判据。 - 用
-c临时覆盖跑一次做 A/B 对照,比直接改文件干净:改文件出了问题你还得回滚,-c只影响这一次。 - 最后拿你真正要访问的那个主机名去测。
limited模式下,域名 A 通不代表域名 B 通。
要把诊断结果贴到工单或 issue 里给别人看,用 codex doctor --json:官方对它的说明是「Emit a redacted machine-readable report」,是脱敏的。即便如此,发出去之前也自己再扫一遍有没有个人目录路径和密钥片段——示例里一律写成 ~/.codex/... 和 <YOUR_API_KEY> 就对了。
什么情况说明根本不是这个原因
这一节是为了让你及时掉头,别在沙箱开关上耗一晚上:
codex doctor的 Connectivity 组本身就是红的。 这一组包含network、websocket、reachability三项,本机在 codex-cli 0.147.0(Windows 11)上websocket显示的是connected (HTTP 101 Switching Protocols) · 15s timeout。要提醒的是,这一组检查的是 Codex 自身到 provider 端点的可达性,和「沙箱内子进程能不能出网」不是同一件事:Connectivity 全绿不代表沙箱里能出网;但反过来,Connectivity 就是红的,那你面对的是整机网络/代理问题,改沙箱开关一点用没有。- 已经在
danger-full-access下了还是不通。 官方对这一档的表述是移除了文件系统和网络边界。边界都撤了还不通,问题在 Codex 之外——系统代理、DNS、公司网关,去那边查。 - 报的是错误 1385,或者初始化就失败了。 那是沙箱用户/登录类型的问题,沙箱压根没起来,谈不上「沙箱里没网」。走上面那套官方四步。
- 看到的是「目录对所有人可写」的告警。 那是 Windows 权限过宽的提示,和出网无关。
- 你在 Linux 或 WSL2 里,而不是 Windows 原生环境。 那套机制是 bwrap,请按 Linux 的路子排,先确认
bubblewrap装没装;Windows 原生沙箱的这些配置和现象对你不适用。 - 改的是
approval_policy。 前面说过了,它管的是「要不要问你」,不管「能不能出网」。审批策略从on-request改成never,只会让失败变得更安静。
最后一句实在话:这四层里,最常见的其实是第 0 步——配置文件写坏了没加载,或者键名拼错被当成字符串吃掉了。先跑 doctor 看那一行,再谈别的。
相关阅读
- Codex 沙箱三种模式怎么选:从「能不能改我的文件」倒推
never不等于放开权限:Codex 里最容易混的三组概念- Codex 审批策略拆解:三档字符串与五个细粒度开关怎么选
- Codex 的六个使用面:一张图看懂该用哪个
本文依据 Codex 官方文档(learn.chatgpt.com/docs/ 的《Sandbox》《Windows sandbox》《Configuration Reference》《Troubleshooting》页面)整理,核对日 2026-08-09;文中标注「本机实测」的部分基于 codex-cli 0.147.0 / Windows 11 环境下的只读命令输出。产品功能、模型与价格以官方最新说明为准。桌面应用与云端部分为官方文档口径,非本机实测。