diff --git a/chv-guest/chv-execd.py b/chv-guest/chv-execd.py index b87c9f5..aa8f062 100644 --- a/chv-guest/chv-execd.py +++ b/chv-guest/chv-execd.py @@ -57,8 +57,18 @@ DEFAULT_TIMEOUT = 120.0 # codex 子进程可透传的环境变量白名单(前缀匹配;调用方 # 传什么别的都丢弃。模型网关 key 走这个口径,不走 argv, # 绝不进任务登记文件与日志)。 +# SUB2API_/XCM_(2026-11-08 真机验证遗留第 1 项补): +# chv-cell 的 FORWARD_ENV_ALLOWLIST 早已接受 SUB2API_API_KEY / +# SUB2API_BASE_URL / XCM_API_KEY,且 host.py 的 sub2api provider +# 直读进程 env 里的 SUB2API_API_KEY + SUB2API_BASE_URL; +# 但 execd 这层白名单没有这两个前缀,调用方传了也会被丢掉, +# 单元内 codex 永远拿不到网关 key(_codex_env 实测: +# SUB2API_API_KEY、SUB2API_BASE_URL、XCM_API_KEY 全被丢弃, +# 只有 OPENAI_* 能通过)。GITEA_TOKEN 仍不在白名单里, +# 绝不进单元。 CODEX_ENV_PREFIXES = ("OPENAI_", "CODEX_", "CHV_MODEL_", - "PLAYWRIGHT_", "CHV_BROWSER_") + "PLAYWRIGHT_", "CHV_BROWSER_", + "SUB2API_", "XCM_") def _atomic_write(path, data: bytes): diff --git a/cloud/tests/test_chv_opt_stage2.py b/cloud/tests/test_chv_opt_stage2.py index ae47f5f..d7770a4 100644 --- a/cloud/tests/test_chv_opt_stage2.py +++ b/cloud/tests/test_chv_opt_stage2.py @@ -222,10 +222,20 @@ class ExecdTest(unittest.TestCase): "GITEA_TOKEN": "must-not-pass", "HOME": "/root", "CHV_MODEL_BASE": "http://x", + # 网关 key(2026-11-08 遗留第 1 项):cell 白名单 + # 早已接受,execd 这层此前丢弃,单元内 codex 拿 + # 不到 key——补前缀后须透传。 + "SUB2API_API_KEY": "sk-sub2api-test", + "SUB2API_BASE_URL": "http://gateway.invalid", + "XCM_API_KEY": "sk-xcm-test", "PLAYWRIGHT_BROWSERS_PATH": "/custom"}) self.assertEqual(env["OPENAI_API_KEY"], "sk-test") self.assertEqual(env["CODEX_FOO"], "yes") self.assertEqual(env["CHV_MODEL_BASE"], "http://x") + self.assertEqual(env["SUB2API_API_KEY"], "sk-sub2api-test") + self.assertEqual(env["SUB2API_BASE_URL"], + "http://gateway.invalid") + self.assertEqual(env["XCM_API_KEY"], "sk-xcm-test") self.assertNotIn("GITEA_TOKEN", env) # HOME 固定为 chv 家目录,不接受调用方传入。 self.assertEqual(env["HOME"], "/home/chv")