fix(worker): env 收敛改黑名单 + 不 detached —— 修 worker 'Not logged in'
cutover 实测:worker 起的 claude 报 Not logged in。根因:① 严格 env allowlist 把 macOS keychain/Security 访问所需的会话变量(USER/LOGNAME/__CF_USER_TEXT_ENCODING/TMPDIR/XPC_* 等, 均非密钥)也滤掉了;本机鉴权走 keychain(无 API_KEY/凭证文件) → 读不到。 ② detached(setsid)另起会话也不利于沿用 daemon 鉴权上下文。 修:workerEnv 改黑名单(会话变量透传保 keychain,仅剥 *_SECRET/*_TOKEN/*_KEY/AWS_/CF_ 等密钥, ANTHROPIC_/CLAUDE_ 始终留);spawn 不 detached(同会话,unref 后孤儿仍被 init 收养存活)。 实测:smoke 任务 worker 真建文件+提交、双复审 approve、到 exec_review。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+17
-10
@@ -68,22 +68,29 @@ test('workerEntry:MAESTRO_WORKER_CMD 覆盖整条命令(空格分隔)', ()
|
||||
else process.env.MAESTRO_WORKER_CMD = prev;
|
||||
});
|
||||
|
||||
test('workerEnv:只透传 PATH/HOME/LANG + ANTHROPIC_/CLAUDE_ 前缀;丢弃无关与 MAESTRO_ 控制变量', () => {
|
||||
test('workerEnv:透传会话/系统变量(keychain 可用),剥离密钥,保留鉴权变量', () => {
|
||||
const env = workerEnv({
|
||||
PATH: '/usr/bin', HOME: '/home/u', LANG: 'en_US.UTF-8',
|
||||
ANTHROPIC_API_KEY: 'sk-x', CLAUDE_CODE_FOO: 'y',
|
||||
USER: 'wj', LOGNAME: 'wj', __CF_USER_TEXT_ENCODING: '0x1F5:0:0', TMPDIR: '/tmp', XPC_SERVICE_NAME: '0',
|
||||
ANTHROPIC_API_KEY: 'sk-x', CLAUDE_CODE_OAUTH_TOKEN: 'oauth-x', CLAUDE_CODE_FOO: 'y',
|
||||
MAESTRO_ORCH_INTERVAL: '15', MAESTRO_DATA_DIR: '/data',
|
||||
SOME_SECRET: 'leak', AWS_SECRET_ACCESS_KEY: 'nope',
|
||||
SOME_SECRET: 'leak', AWS_SECRET_ACCESS_KEY: 'nope', GITHUB_TOKEN: 'gh', CF_API_TOKEN: 'cf',
|
||||
});
|
||||
assert.equal(env.PATH, '/usr/bin');
|
||||
assert.equal(env.HOME, '/home/u');
|
||||
assert.equal(env.LANG, 'en_US.UTF-8');
|
||||
// 会话/系统变量透传(macOS keychain/Security 访问需要它们)
|
||||
for (const k of ['PATH', 'HOME', 'LANG', 'USER', 'LOGNAME', '__CF_USER_TEXT_ENCODING', 'TMPDIR', 'XPC_SERVICE_NAME']) {
|
||||
assert.ok(env[k] !== undefined, `会话变量 ${k} 应透传`);
|
||||
}
|
||||
// 鉴权变量始终保留(即便名含 TOKEN/KEY)
|
||||
assert.equal(env.ANTHROPIC_API_KEY, 'sk-x');
|
||||
assert.equal(env.CLAUDE_CODE_OAUTH_TOKEN, 'oauth-x');
|
||||
assert.equal(env.CLAUDE_CODE_FOO, 'y');
|
||||
assert.equal(env.MAESTRO_DATA_DIR, '/data'); // 例外:worker 须看同一 runs/ 目录
|
||||
assert.equal(env.MAESTRO_ORCH_INTERVAL, undefined, 'daemon 控制变量不下传');
|
||||
assert.equal(env.SOME_SECRET, undefined, '无关变量不下传');
|
||||
assert.equal(env.AWS_SECRET_ACCESS_KEY, undefined, '无关密钥不下传');
|
||||
assert.equal(env.MAESTRO_DATA_DIR, '/data'); // worker 须看同一 runs/ 目录
|
||||
assert.equal(env.MAESTRO_ORCH_INTERVAL, '15'); // 非密钥 → 透传(黑名单语义)
|
||||
// 真正的密钥类被剥离
|
||||
assert.equal(env.SOME_SECRET, undefined, '*_SECRET 剥离');
|
||||
assert.equal(env.AWS_SECRET_ACCESS_KEY, undefined, 'AWS 密钥剥离');
|
||||
assert.equal(env.GITHUB_TOKEN, undefined, 'GITHUB_TOKEN 剥离');
|
||||
assert.equal(env.CF_API_TOKEN, undefined, 'CF token 剥离');
|
||||
});
|
||||
|
||||
// ───────────────────────── tick 顺序:ingest + reaper 先于领取 ─────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user