From 3fa5bb7f5f815dde30643f34eaccae9d00870005 Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Thu, 8 Oct 2026 11:02:12 -0700 Subject: [PATCH] fix(voice): start codex login without the server's provider secrets The login child inherited the whole server environment, including OPENAI_API_KEY and every other provider credential. Pass only what Codex needs to find its home, open a browser and reach OpenAI through a proxy. --- server/providers/openai/codex-auth.js | 17 ++++++++++++++++- src/codexOauthRealtime.test.mjs | 19 +++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/server/providers/openai/codex-auth.js b/server/providers/openai/codex-auth.js index 376830cf4..5f16ee824 100644 --- a/server/providers/openai/codex-auth.js +++ b/server/providers/openai/codex-auth.js @@ -138,6 +138,21 @@ export function resolveCodexExecutable({ return 'codex'; } +// What `codex login` needs to find its home, open a browser and reach OpenAI. +// The server's own environment also holds every provider secret, so the +// child receives only these names. +const CODEX_LOGIN_ENV = + /^(?:PATH|PATHEXT|HOME|USER|USERNAME|LOGNAME|SHELL|LANG|LANGUAGE|LC_[A-Z_]+|TERM|TZ|TMPDIR|TEMP|TMP|XDG_[A-Z_]+|DISPLAY|WAYLAND_DISPLAY|DBUS_SESSION_BUS_ADDRESS|BROWSER|WSL_[A-Z_]+|WSLENV|(?:HTTPS?|ALL|NO)_PROXY|SSL_CERT_(?:FILE|DIR)|NODE_EXTRA_CA_CERTS|SYSTEMROOT|WINDIR|COMSPEC|USERPROFILE|APPDATA|LOCALAPPDATA|PROGRAMDATA|HOMEDRIVE|HOMEPATH|CODEX_[A-Z_]+)$/i; + +/** The environment `codex login` runs with: the allowlist, then `CODEX_HOME`. */ +export function codexLoginEnvironment(environment, codexHome) { + const env = {}; + for (const [name, value] of Object.entries(environment || {})) + if (CODEX_LOGIN_ENV.test(name) && value !== undefined) env[name] = value; + env.CODEX_HOME = codexHome; + return env; +} + export function startCodexChatGptLogin({ spawnImpl = spawn, environment = process.env, @@ -182,7 +197,7 @@ export function startCodexChatGptLogin({ cwd: home, detached: true, stdio: 'ignore', - env: { ...environment, CODEX_HOME: loginHome }, + env: codexLoginEnvironment(environment, loginHome), }); } catch { fail(); diff --git a/src/codexOauthRealtime.test.mjs b/src/codexOauthRealtime.test.mjs index 391082ff4..07e1a7dcc 100644 --- a/src/codexOauthRealtime.test.mjs +++ b/src/codexOauthRealtime.test.mjs @@ -168,7 +168,13 @@ test('Codex login resolves an installed executable before PATH and starts browse const pending = startCodexChatGptLogin({ executable: '/fixture/codex', home: '/home/fixture', - environment: { PATH: '/fixture' }, + environment: { + PATH: '/fixture', + https_proxy: 'http://proxy.fixture:8080', + OPENAI_API_KEY: 'fixture-api-key', + GOOGLE_MAPS_SERVER_API_KEY: 'fixture-google-key', + OPENSKY_CLIENT_SECRET: 'fixture-opensky-secret', + }, spawnImpl(command, args, options) { calls.push({ command, args, options }); queueMicrotask(() => child.emit('spawn')); @@ -181,9 +187,14 @@ test('Codex login resolves an installed executable before PATH and starts browse assert.deepEqual(calls[0].args, ['login']); assert.equal(calls[0].options.detached, true); assert.equal(calls[0].options.stdio, 'ignore'); - assert.equal( - calls[0].options.env.CODEX_HOME, - path.join('/home/fixture', '.codex'), + assert.deepEqual( + calls[0].options.env, + { + PATH: '/fixture', + https_proxy: 'http://proxy.fixture:8080', + CODEX_HOME: path.join('/home/fixture', '.codex'), + }, + 'provider secrets stay out of the login process', ); child.emit('exit', 1); assert.deepEqual(await login.completion, { exitCode: 1 });