From 78d51dcebe9e4fe21ccdc63052909fddb630e572 Mon Sep 17 00:00:00 2001 From: pashpashpash Date: Tue, 28 Apr 2026 13:34:14 -0700 Subject: [PATCH] Clear Codex app-server env keys case-insensitively on Windows (#73102) * fix(codex): clear app-server env case variants * fix(codex): avoid repeated env clear scans --- .../src/app-server/transport-stdio.test.ts | 22 ++++++++++++++++ .../codex/src/app-server/transport-stdio.ts | 26 +++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/extensions/codex/src/app-server/transport-stdio.test.ts b/extensions/codex/src/app-server/transport-stdio.test.ts index 9e44f452344..a426db00f07 100644 --- a/extensions/codex/src/app-server/transport-stdio.test.ts +++ b/extensions/codex/src/app-server/transport-stdio.test.ts @@ -112,6 +112,28 @@ describe("resolveCodexAppServerSpawnEnv", () => { }); }); + it("clears denied env vars case-insensitively on Windows", () => { + expect({ + ...resolveCodexAppServerSpawnEnv( + { + env: { + OpenAI_Api_Key: "configured-openai-key", + Other: "configured", + }, + clearEnv: ["OPENAI_API_KEY", " CODEX_API_KEY ", ""], + }, + { + Codex_Api_Key: "parent-codex-key", + KEEP: "parent", + }, + "win32", + ), + }).toEqual({ + KEEP: "parent", + Other: "configured", + }); + }); + it("uses a null-prototype env map and ignores prototype-polluting keys", () => { const overrides = Object.create(null) as Record; Object.defineProperty(overrides, "__proto__", { diff --git a/extensions/codex/src/app-server/transport-stdio.ts b/extensions/codex/src/app-server/transport-stdio.ts index 5efb7f217a5..287da8dea94 100644 --- a/extensions/codex/src/app-server/transport-stdio.ts +++ b/extensions/codex/src/app-server/transport-stdio.ts @@ -46,16 +46,38 @@ export function resolveCodexAppServerSpawnInvocation( export function resolveCodexAppServerSpawnEnv( options: Pick, baseEnv: NodeJS.ProcessEnv = process.env, + platform: NodeJS.Platform = process.platform, ): NodeJS.ProcessEnv { const env = Object.create(null) as NodeJS.ProcessEnv; copySafeEnvironmentEntries(env, baseEnv); copySafeEnvironmentEntries(env, options.env ?? {}); - for (const key of options.clearEnv ?? []) { - delete env[key]; + const keysToClear = normalizedEnvironmentKeys(options.clearEnv ?? []); + if (platform === "win32") { + const lowerCaseKeysToClear = new Set(keysToClear.map((key) => key.toLowerCase())); + for (const candidate of Object.keys(env)) { + if (lowerCaseKeysToClear.has(candidate.toLowerCase())) { + delete env[candidate]; + } + } + } else { + for (const key of keysToClear) { + delete env[key]; + } } return env; } +function normalizedEnvironmentKeys(rawKeys: readonly string[]): string[] { + const keys: string[] = []; + for (const rawKey of rawKeys) { + const key = rawKey.trim(); + if (key.length > 0) { + keys.push(key); + } + } + return keys; +} + function copySafeEnvironmentEntries( target: NodeJS.ProcessEnv, source: NodeJS.ProcessEnv | Record,