Codex shell 环境变量策略:哪些变量会被带进子进程

2026-08-09

Codex(OpenAI Codex)的 CLI 会替你派生子进程去跑命令。只要你在自己的 shell 里 export 过东西——公司代理、私有 npm registry 的凭据、内网证书路径、各种 *_API_KEY——就绕不开一个问题:这些变量到底有没有被带进那个子进程?

这个问题往两个方向踩坑。一个方向是泄露:你不希望某些变量出现在一个会把命令输出回传给模型的进程里。另一个方向恰恰相反,是”为什么这条命令我自己在终端敲能跑,交给 Codex 跑就失败”——多半是子进程少了某个变量。这两类问题在 Codex CLI 里由同一组配置键决定,就是 config.toml 里的 shell_environment_policy

下面这些内容对应官方《Configuration Reference》页,核对日 2026-08-09;带「本机实测」的部分来自 codex-cli 0.147.0(Windows 11)上执行的只读命令。

这一组键长什么样

配置文件默认在 ~/.codex/config.toml(也就是 $CODEX_HOME/config.toml)。和 shell 环境直接相关的键,官方参考页上一共列了这些:

类型默认官方说明
allow_login_shellbooleantrue允许 shell 工具使用登录 shell 语义
shell_environment_policy.inheritstringall / core / none
shell_environment_policy.ignore_default_excludesbooleantrue过滤前保留含 KEY、SECRET、TOKEN 的变量
shell_environment_policy.filtersmap大小写不敏感的环境变量模式过滤
shell_environment_policy.exclude / include_onlyarray<string>旧版排除 / 白名单
shell_environment_policy.setmap排除之后再注入的显式环境值
shell_environment_policy.experimental_use_profileboolean派生子进程时使用用户 shell profile

先说一句对这张表的读法:官方在这一页给的是键的清单,不是一张完整的流水线图。从各键的说明文字里能确定的先后关系只有两处——ignore_default_excludes 作用在”过滤前”,set 作用在”排除之后”。除此之外这几个键谁先谁后、filters 和旧版 exclude 同时写会怎么合并,配置参考页没写死。没写死的部分就别靠猜,需要的话在自己机器上验证,或者去看官方那一页的原文(任何文档页 URL 后面加 .md 后缀就能拿到 Markdown 版本,方便直接检索键名)。

最容易读反的一个键:ignore_default_excludes

这是这组配置里名字起得最容易误导的一个,值得单独讲。

ignore_default_excludes 默认是 true,它的含义是保留含 KEY、SECRET、TOKEN 的变量,而不是排除它们。名字直译过来是”忽略默认排除项”,很多人第一眼会理解成”忽略掉那些敏感变量”,正好反了——被忽略的是那条默认排除规则,规则不执行,于是变量留下来。

判断依据很直接:如果你没有动过这个键,那么按官方给的默认值,你 shell 里那些名字里带 KEY/SECRET/TOKEN 字样的变量,在过滤阶段之前是被保留着的。 你如果长期在 .bashrc 或 PowerShell profile 里 export 着 <YOUR_API_KEY> 这类东西,这就不是个理论问题。

想收紧,有几条路,代价各不相同:

  • ignore_default_excludes 设成 false,让那条默认排除规则恢复生效。这是改动最小的一步,但它只覆盖”名字里带那三个词”的变量——变量名叫 NPM_AUTH 的它管不着。
  • shell_environment_policy.filters 按模式过滤,官方注明是大小写不敏感的。适合你自己清楚要挡哪一类命名。
  • 从源头缩小,直接改 inherit。这是最彻底的做法,也最容易把命令搞坏,下一节单说。

顺带提醒:excludeinclude_only 在官方表里明确标了是旧版(legacy)的排除 / 白名单键。老博客和老配置里全是它俩。新写配置时优先用 filters,遇到别人给的配置片段也要意识到它可能来自旧版写法。

inherit 三个取值怎么选

inherit 决定的是”起点集合”——子进程从你的环境里继承多少。官方给的取值是 allcorenone 三个。

这一页没有列出 core 具体包含哪些变量。我不打算替官方补这个清单,因为那是纯猜。这一点本身就是个有用的结论:网上凡是斩钉截铁告诉你”core 就是 PATH、HOME、USER 这几个”的说法,你都该去核一下出处。要确定就自己在本机验证。

能给的决策路径是这样的:

  • 默认怎么跑就怎么跑,先别动。 除非你有明确的诉求(合规要求、或者已经出了故障),否则改 inherit 的收益远小于它引入的”在我这儿能跑”类怪问题。
  • 想要复现性、想让不同人的机器行为一致 → 往 nonecore 收,再用 set 把子进程真正需要的变量显式写回去。好处是子进程环境变成了写在配置里的、可评审的一份清单;代价是你得自己把缺的补齐,而且补漏的过程会伴随一串”command not found”式的失败。
  • 一堆工具链依赖你终端里的环境(自定义 PATH、代理、编译器环境) → 老老实实 all,把安全边界交给沙箱和权限档去管,而不是靠删环境变量。

最后这条要说透:环境变量策略不是沙箱。它管的是”子进程能看到什么变量”,管不了”子进程能写哪些文件、能连哪些网”。后者是 sandbox_moderead-only / workspace-write / danger-full-access)和 permissions.<name>.* 那一套的活儿。把变量删干净不等于这个进程干不了坏事,别拿前者替代后者。

set 是唯一”确定能进去”的通道

set 是一个 map,官方说明是”排除之后再注入的显式环境值”。这句里的排除之后是关键:它在过滤之后执行,所以你在 set 里写的东西不会被前面的过滤规则吃掉。

也正因为如此,收紧 inherit 之后靠 set 补回来这条路才成立。一个组合示例:

[shell_environment_policy]
inherit = "core"
ignore_default_excludes = false
set = { LANG = "en_US.UTF-8" }

以上为按官方文档键位组合的示例,未逐项实测,以官方文档为准。

对应的临时试法,不用改文件:官方 codex --help 里给出的 -c 用法示例之一就是这个键,可以原样抄:

codex -c shell_environment_policy.inherit=all

-c 的规则是:点号路径表示嵌套,value 按 TOML 解析,解析失败则按字面字符串处理。这条规则有个副作用值得记住——布尔值写错了不会报错,会静默变成一个字符串。所以 -c 只适合做”换个取值试一下”这种快速验证,长期设置还是写进 config.toml 里,改完能被 review。

别把这几个 env 混为一谈

env 这个词在 Codex 的配置里出现在好几处,管的东西完全不同:

  • shell_environment_policy.*:本文讲的,管 shell 工具派生子进程的环境。
  • mcp_servers.<id>.env / env_vars:给某个 MCP server 进程的环境,跟 shell 工具是两条线。
  • model_providers.<id>.env_key存放 API key 的环境变量名。官方在这一页明确写了 experimental_bearer_token 不建议用,应改用 env_key

第三条和本文的连接点在于:既然官方推荐 key 走环境变量,那你机器上就一定存在这么一个变量;它会不会被带进 shell 子进程,就回到了前面 ignore_default_excludes 那一节的判断。这两件事读的是同一份环境,只是消费者不同。

一个可以直接用的实测结论:在 codex-cli 0.147.0(Windows 11)上执行 codex mcp list,表头是 Name | Command | Args | Env | Cwd | Status | Auth,其中 Env 列里的环境变量值会被打成 *****,只显示键名。也就是说这条命令的输出自带脱敏,贴给同事排查是安全的。但要分清:命令输出被打码,不等于这个变量没有被传给 server 进程——脱敏发生在显示层。

登录 shell 与 profile:可控性的分水岭

allow_login_shell 默认 true,允许 shell 工具使用登录 shell 语义。shell_environment_policy.experimental_use_profile 则是”派生子进程时使用用户 shell profile”,注意它的键名前缀就带 experimental——官方把它标成实验性功能,不要在 CI 或团队统一配置里当稳定特性推。

判断依据在于团队规模:如果你们每个人的 .bashrc.zshrc、PowerShell profile 都不一样,让子进程去跑 profile 就意味着把这些差异原样带进来。个人机器上这可能是便利(你在 profile 里配的别名和 PATH 都在),多人协作时它就是”在我机器上能跑”的温床。反过来,如果你的构建脚本本来就依赖 profile 里的初始化(版本管理器之类),关掉它反而会让命令莫名其妙找不到工具。没有普适答案,只有一条:这是一个会影响可复现性的开关,出问题时要把它列进怀疑清单。

Windows 上额外要看两件事

第一件是 features.unified_exec。官方给的默认值是 true,但明确标了 Windows 除外。在 codex-cli 0.147.0(Windows 11)上执行 codex features listunified_exec 这一行的阶段是 stable、当前生效值是 false——和官方文档的说明对得上。这条的实用含义是:你在英文文档或博客上看到的、基于 unified exec 的命令执行行为描述,在 Windows 上可能根本没启用。改环境变量策略之前,先用 codex features list 看一眼你这台机器上的生效值是什么,别拿别人平台的结论套自己。

第二件是 features.shell_snapshot,默认 true,官方说明是”快照 shell 环境以加速重复命令”。配置参考页对它只有这一句,没写快照的粒度和失效时机,所以我不会告诉你”改完变量要多久才生效”。但排查”我明明改了环境变量、行为却没变”这类现象时,它值得进你的怀疑清单,而成本最低的排除法是重开一个会话再试。

改完之后怎么确认它真的生效

这是这组配置最实际的一环,因为 shell_environment_policy.ignore_default_excludes 这种键名有 40 多个字符,拼错概率相当高。

第一步,跑 doctor 看配置有没有被加载。 在 codex-cli 0.147.0(Windows 11)上故意用 codex -c 'features=[unclosed' doctor --summary 传一段语法不合法的 TOML,结果是:命令没有崩溃退出,doctor 照常跑完,但输出里出现了这么一行:

✗ config       config could not be loaded - Fix the reported config error, then rerun codex doctor.

这个行为很有价值——配置坏了 Codex 不会拦着你,它照跑,只是你的配置一个字都没生效。所以”我改了配置怎么没反应”的第一步永远是 codex doctor --summary,先确认 config 这一行不是

第二步,别指望 --strict-config 帮你抓拼写错误。 它的说明是”config.toml 里出现本版本不认识的字段时直接报错退出”,但在 codex-cli 0.147.0(Windows 11)上实测:把键名故意拼错成 model_reasoning_effortt 再配 --strict-config exec --help,命令正常打印了 help,没有报未知字段错误。说明这个校验发生在真正加载配置去跑会话的路径上,--help 这类不进入会话的调用不触发它。想让它替你把关,就得用一条真正会进入会话的命令。

第三步,验证变量本身。 到这一步就得你自己在本机上跑了。我们这次采集从头到尾没有发起过任何模型对话请求,所以我不会给你一个”预期输出”让你对答案——那是编的。你要做的是在自己机器上,用你平时的用法让它打印一次环境变量,然后对照你写进 set 的那几个键看在不在。

顺便说一句版本纪律:同一台机器上,本次采集开头 codex --version 得到的是 codex-cli 0.131.0,十几分钟后再执行同一命令变成了 codex-cli 0.147.0check_for_update_on_startup 默认为 true)。配置键的默认值和特性阶段都会随版本变,所以排查这类问题时,以你当次 codex --version 的实时输出为准,不要用记忆里的版本号,也不要直接照抄半年前的博客配置。

什么时候不该在这上面花时间

  • 只是想让某个命令别被拦住——那是审批策略(approval_policy)和沙箱模式的事,跟环境变量无关。
  • 想靠删变量做安全隔离——前面说过,这组键不是安全边界。真正的边界在沙箱与权限档那一层,而且官方对 Windows 的 unelevated 沙箱自己都写了”保护更弱”,谁都不该在这件事上给你打包票。
  • 文档没写的细节想问清楚——配置参考页 URL 后加 .md 拿 Markdown 版直接搜键名,站点还提供 llms.txt(页面索引)和 llms-full.txt(合并全文),比在搜索引擎里翻二手结论靠谱得多。

相关阅读


本文依据 Codex 官方文档(learn.chatgpt.com/docs/ 的《Configuration Reference》《Sandbox》页面)整理,核对日 2026-08-09;文中标注「本机实测」的部分基于 codex-cli 0.147.0 / Windows 11 环境下的只读命令输出。产品功能、模型与价格以官方最新说明为准。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。