feat(security): 工作区里有 .env 就拒绝启动 Codex,逃生阀显式且不静默 (#52) - #53
Merged
Conversation
`lc code` 在 CWD 里启动 Codex,配置是 approval_policy = "never";容器里更是 danger-full-access。工作区里躺着 .env 的话,一句 `cat .env` 就能读走全部上游的 地址与凭证——#42 收紧的进程环境这条读法完全绕过去了。 #46 / #50 都只做到「警告 + 文档」。#52 评估了把 .env 搬出仓库目录(A 方案), 结论是不搬:它会破坏「解包 → 目录里什么都有 → 删目录即干净卸载」这个对隔离网 交付的承诺。改成默认拒绝 + 显式放行。 - bin/lc: warn_env_in_workspace() → guard_env_in_workspace(reg, allow), 非零退出;`lc code --allow-workspace-secrets` 放行。flag 从透传给 Codex 的 参数里摘掉(Codex 不认识它,会以 unexpected argument 退出)。 - docker/entrypoint.sh: 同机制,逃生阀是 AIRGAP_ALLOW_WORKSPACE_SECRETS=1; 报错教的是挂载写法而不是 cd(容器里没有别的目录可去)。 - 两条防退化约束写进代码注释,替换掉原来那段「不阻断的理由」: 放行时仍然打印完整警告;CLI 侧不提供环境变量形式的全局开关。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #52
按 维护者决策 实现:不搬
.env,把 happy path 从「会被无视的警告」改成「硬停 + 显式放行」。改了什么
1.
bin/lc:warn_env_in_workspace()→guard_env_in_workspace(reg, allow).env在 Codex 工作区这棵树里 → 打印完整警告后非零退出,不启动 Codex。逃生阀:
lc code --allow-workspace-secrets。报错说清三件事(决策第 1 条要求的信息密度,沿用 #49 那条量化文案):
flag 会从透传给 Codex 的参数里摘掉。这条不是洁癖:Codex 不认识它,透传下去会以一句
unexpected argument直接退出,用户看到的就成了「按提示放行之后反而更坏了」。按精确串摘,不做前缀匹配。2.
docker/entrypoint.sh:同机制,逃生阀是环境变量AIRGAP_ALLOW_WORKSPACE_SECRETS=1。两处和 CLI 侧不同,都是刻意的:cd—— 容器里没有「换个目录跑」这个选项,用户能改的只有-v。1才放行。=0/=false/ 空值都当拒绝,因为写下=0的人的意思显然是「关」,而这个检查里「静默地当成开」是最坏的失效方式。3. 两条防退化约束(决策第 3 条 + 后续那条评论)
export一次就全局静默,那才是真正的退化。容器侧不得不用环境变量(那边没有命令行可加),代码注释里写明这是被迫、不构成先例。按要求,
bin/lc里原来那段「不阻断的理由」和entrypoint.sh:56-57同样的注释都替换掉了,换成「为什么现在阻断」+ 上面两条约束,免得将来有人读到旧注释又改回警告。A 方案被否的理由(离线包自包含)也留在注释和 threat-model 里,附 issue #52 链接作为将来重新评估的起点。4. 文档
README.md/README.zh-CN.md[!IMPORTANT]从「会警告」改成「会阻断」+ flag 说明;命令表补上 flagdocs/threat-model.mddocs/offline-deployment.mddocs/troubleshooting.mdCHANGELOG.mdlc code的人现在需要 flag 或者cd怎么验证的
CI 断言(决策第 5 条要求各补三条,都在已被
ci.yml调用的脚本里,不需要动.github/)scripts/test-lc-commands.sh[6f2] 重写(ci.yml已有bash scripts/test-lc-commands.sh):.env→ 非零退出、无Traceback、$CODEX_LOG为空(压根没启动 Codex),文案含文件名 /2 个上游/cd指引 /已拒绝启动 Codex/ 逃生阀名字--profile beta)、仍然打印警告(文件名 +2 个上游+显式放行)、flag 没透传给 codex、其它参数照旧透传.env→ 正常启动、不打印警告(防误报)外加:仓库上一层目录也阻断(判据是「
.env在 CWD 树里」而不是CWD == ROOT);带 flag 但不该响的目录里不许凭空报警;提示里不含$CANARY_KEY/ master key 的值。变异测试:把
die(...)换成return,断言第 1 条会变红。没有这条,「非零退出」这个断言可能是靠别的原因满足的——找不到注入点就直接::error::报红,不让它静默失效(照 [6d] 已有的形态写)。scripts/test-entrypoint.sh(ci.yml已调用):同样三条,另加「只有=1放行,0/false/ 空值都必须拒绝」和「拒绝时$WORK/args为空」。本地全套(runner 无 GPU / 无 API Key)
真实模型路径(
smoke.py/test-codex.sh)本地跑不了,未验证。不做(决策明确排除)
.envAIRGAP_CODER_ENV这类位置配置项关 issue 的方式
按决策最后一条,合并后在 #52 的关闭评论里保留 A 方案的完整取舍分析,作为将来出现第三条暴露路径时重新评估的起点。
🤖 Generated with Claude Code