openclaw - ✅(Solved) Fix Codex app-server inherits OPENAI_API_KEY from gateway and switches to API key mode [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#73057Fetched 2026-04-28 06:28:03
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Assignees
Timeline (top)
assigned ×1closed ×1cross-referenced ×1

When OpenClaw starts the native Codex app-server via stdio, the child process inherits the full gateway environment, including OPENAI_API_KEY. On a mixed setup where OpenClaw needs OPENAI_API_KEY for OpenAI embeddings/providers but Codex CLI is logged in with ChatGPT/OAuth, the Codex app-server UI/session reports Account API key configured (run codex login to use ChatGPT) and appears to use API-key mode instead of the ChatGPT/OAuth Codex account.

This makes it hard to use:

  • OpenAI API key for embeddings / direct OpenAI provider access, and
  • native Codex app-server with ChatGPT/Codex OAuth quota

in the same OpenClaw service environment.

Error Message

  1. In a shell, Codex is logged in using ChatGPT/OAuth:

Root Cause

  • OpenClaw: 2026.4.25 (aa36ee6)
  • Codex CLI: codex-cli 0.125.0
  • Native Codex app-server enabled via Codex plugin
  • codex login status in the terminal reports: Logged in using ChatGPT
  • ~/.codex/auth.json has auth_mode = "chatgpt", token credentials present, and no OPENAI_API_KEY
  • OpenClaw gateway process environment has OPENAI_API_KEY set because it is needed for OpenAI embeddings/providers

Fix Action

Fixed

PR fix notes

PR #73063: Keep Codex subscription runs from inheriting API keys

Description (problem / solution / changelog)

Some OpenClaw installs need OPENAI_API_KEY in the Gateway environment for embeddings, PI, or direct OpenAI model calls, while native Codex app-server turns should use the user's Codex or ChatGPT subscription login. Before this, the stdio Codex child inherited the Gateway environment by default, so a shared key could silently steer Codex runs onto Platform API billing.

This keeps the public appServer.clearEnv knob, but makes the common switch automatic. OpenClaw now selects Codex app-server auth in the same shape users expect from /models: an explicit OpenClaw Codex auth profile first, then the app-server's existing account such as a local Codex CLI ChatGPT sign-in, then CODEX_API_KEY and OPENAI_API_KEY only for local stdio app-server fallback when no account is available and the app-server still needs OpenAI auth.

When the selected Codex auth is subscription-style OAuth or token auth, OpenClaw removes both CODEX_API_KEY and OPENAI_API_KEY from the spawned Codex child process. Explicit Codex API-key profiles and local no-account env fallback still use app-server login, so users who intentionally want Codex on API-key auth can choose that path without relying on accidental env inheritance. WebSocket app-server connections do not receive Gateway env API-key fallback, and local fallback reads the same effective stdio environment after appServer.env and appServer.clearEnv have been applied.

The shared-client key uses a process-local HMAC for app-server environment values and auth tokens, so internal env overrides still produce distinct clients without putting raw values or reusable secret fingerprints into the key string. The stdio env merge now uses a null-prototype map and ignores prototype-polluting keys. The auth bridge and stdio transport coverage now exercise local/default subscription auth, explicit OAuth and token profiles, explicit API-key profiles, local stdio env fallback, effective env clearing, existing app-server accounts, websocket connections, and child-process env clearing.

The user story this needs to protect is simple: a user keeps a real OPENAI_API_KEY in the OpenClaw Gateway environment because some features should use Platform billing, then switches their OpenAI model runtime to Codex because they expect ChatGPT or Codex subscription auth. Their Codex turns should not silently start spending through the inherited Gateway key. At the same time, a user who explicitly chooses PI or an API-key Codex profile should still get API-key behavior.

I proved that story with a live end-to-end smoke on this branch. I used real OpenClaw agent turns, not just unit tests or source inspection, and shaped the smoke as a positive control, a negative control, and then the Codex target case.

First, PI with a validated OpenAI Platform key succeeded:

OPENAI_API_KEY=<valid> OPENCLAW_AGENT_RUNTIME=pi node scripts/run-node.mjs agent --agent main --session-id smoke-pi-20260427193445-69302 --model openai/gpt-5.4 --thinking low --message "Reply with exactly OPENCLAW_PI_SMOKE_20260427193445-69302 and nothing else." --local --json

The result was a successful agent turn. The JSON metadata reported agentHarnessId: "pi", provider openai, model gpt-5.4, and the assistant returned exactly OPENCLAW_PI_SMOKE_20260427193445-69302.

Second, PI with a deliberately bogus API key failed the way it should:

OPENAI_API_KEY=sk-invalid-openclaw-smoke-... OPENCLAW_AGENT_RUNTIME=pi node scripts/run-node.mjs agent --agent main --session-id smoke-pi-invalid-20260427193647-70546 --model openai/gpt-5.4 --thinking low ... --local --json

That run exited with 401 Incorrect API key provided. This is the control that proves PI was genuinely using the env API-key route, not some already-authenticated local subscription path.

Third, Codex with the same kind of bogus env keys succeeded:

OPENAI_API_KEY=sk-invalid-openclaw-smoke-... CODEX_API_KEY=sk-invalid-openclaw-smoke-... OPENCLAW_AGENT_RUNTIME=codex node scripts/run-node.mjs agent --agent main --session-id smoke-codex-20260427193718-70903 --model openai/gpt-5.4 --thinking low --message "Reply with exactly OPENCLAW_CODEX_SMOKE_20260427193718-70903 and nothing else." --local --json

The result was a successful Codex agent turn. The JSON metadata reported agentHarnessId: "codex", provider openai, model gpt-5.4, and the assistant returned exactly OPENCLAW_CODEX_SMOKE_20260427193718-70903. The Codex sidecar recorded a real Codex thread id, 019dd14e-1df2-72e0-a494-7b1565d13412. The harness auth home reported auth_mode: "chatgpt" with no stored OpenAI API key, and codex login status for that same harness auth home reported Logged in using ChatGPT.

That is the important falsifiable proof: the same bogus env key that breaks PI does not break Codex on this branch. PI still uses API-key auth when told to, while Codex subscription auth no longer inherits Gateway API-key billing by accident.

I am confident this covers the user story because the smoke first proves the parent env key can make a real OpenAI turn succeed or fail through PI, then proves Codex survives the same poisoned parent env while using ChatGPT subscription auth. The current PR head has the same Codex runtime and auth codepaths as the live-smoked implementation; the later rebase only changed docs/changelog wording and added the boundary test fix that made the refreshed CI lane green.

Fixes #73057.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/plugins/codex-harness.md (modified, +61/-19)
  • docs/providers/openai.md (modified, +20/-0)
  • extensions/codex/openclaw.plugin.json (modified, +9/-0)
  • extensions/codex/src/app-server/auth-bridge.test.ts (modified, +311/-10)
  • extensions/codex/src/app-server/auth-bridge.ts (modified, +89/-3)
  • extensions/codex/src/app-server/config.test.ts (modified, +72/-0)
  • extensions/codex/src/app-server/config.ts (modified, +27/-5)
  • extensions/codex/src/app-server/shared-client.ts (modified, +2/-0)
  • extensions/codex/src/app-server/transport-stdio.test.ts (modified, +62/-1)
  • extensions/codex/src/app-server/transport-stdio.ts (modified, +26/-5)
  • src/plugins/contracts/boundary-invariants.test.ts (modified, +41/-8)

Code Example

$ codex login status
   Logged in using ChatGPT

---

Account API key configured (run codex login to use ChatGPT)

---

/usr/lib/node_modules/openclaw/dist/extensions/codex/shared-client-CpOyZpH5.js

---

function createStdioTransport(options) {
  const env = {
    ...process.env,
    ...options.env
  };
  for (const key of options.clearEnv ?? []) delete env[key];

  return spawn(invocation.command, invocation.args, {
    env,
    ...
  });
}

---

clearEnv: [...options.clearEnv ?? []].toSorted(),

---

/usr/lib/node_modules/openclaw/dist/extensions/codex/openclaw.plugin.json

---

{
  "plugins": {
    "entries": {
      "codex": {
        "config": {
          "appServer": {
            "clearEnv": ["OPENAI_API_KEY"]
          }
        }
      }
    }
  }
}

---

"clearEnv": ["OPENAI_API_KEY"]
RAW_BUFFERClick to expand / collapse

Summary

When OpenClaw starts the native Codex app-server via stdio, the child process inherits the full gateway environment, including OPENAI_API_KEY. On a mixed setup where OpenClaw needs OPENAI_API_KEY for OpenAI embeddings/providers but Codex CLI is logged in with ChatGPT/OAuth, the Codex app-server UI/session reports Account API key configured (run codex login to use ChatGPT) and appears to use API-key mode instead of the ChatGPT/OAuth Codex account.

This makes it hard to use:

  • OpenAI API key for embeddings / direct OpenAI provider access, and
  • native Codex app-server with ChatGPT/Codex OAuth quota

in the same OpenClaw service environment.

Environment

  • OpenClaw: 2026.4.25 (aa36ee6)
  • Codex CLI: codex-cli 0.125.0
  • Native Codex app-server enabled via Codex plugin
  • codex login status in the terminal reports: Logged in using ChatGPT
  • ~/.codex/auth.json has auth_mode = "chatgpt", token credentials present, and no OPENAI_API_KEY
  • OpenClaw gateway process environment has OPENAI_API_KEY set because it is needed for OpenAI embeddings/providers

Observed behavior

  1. In a shell, Codex is logged in using ChatGPT/OAuth:

    $ codex login status
    Logged in using ChatGPT
  2. The native Codex app-server session launched by OpenClaw shows API-key mode instead:

    Account API key configured (run codex login to use ChatGPT)
  3. Inspecting running processes shows that the OpenClaw-started Codex app-server inherits OPENAI_API_KEY from the gateway/plugin process environment.

Code path

In the installed bundle:

/usr/lib/node_modules/openclaw/dist/extensions/codex/shared-client-CpOyZpH5.js

createStdioTransport(options) builds the app-server child process env from the full parent process env:

function createStdioTransport(options) {
  const env = {
    ...process.env,
    ...options.env
  };
  for (const key of options.clearEnv ?? []) delete env[key];

  return spawn(invocation.command, invocation.args, {
    env,
    ...
  });
}

So unless options.clearEnv contains OPENAI_API_KEY, the Codex app-server receives the global OpenClaw service API key.

There appears to be internal support for clearEnv in the start options key:

clearEnv: [...options.clearEnv ?? []].toSorted(),

but the bundled Codex plugin config schema does not expose appServer.env or appServer.clearEnv:

/usr/lib/node_modules/openclaw/dist/extensions/codex/openclaw.plugin.json

The appServer config has additionalProperties: false, so users cannot currently configure:

{
  "plugins": {
    "entries": {
      "codex": {
        "config": {
          "appServer": {
            "clearEnv": ["OPENAI_API_KEY"]
          }
        }
      }
    }
  }
}

Expected behavior

A global OPENAI_API_KEY needed by OpenClaw for embeddings/providers should not automatically force the native Codex app-server into API-key mode when the intended Codex auth profile / local Codex login is ChatGPT/OAuth.

At minimum, there should be a supported way to prevent selected environment variables from being inherited by the Codex app-server process.

Suggested fixes

Possible approaches:

  1. Expose plugins.entries.codex.config.appServer.clearEnv and/or appServer.env in the Codex plugin config schema.
  2. Default-clear OPENAI_API_KEY for Codex app-server stdio launches when a ChatGPT/OAuth Codex auth profile is intended.
  3. Provide a documented supported way to run native Codex app-server with a clean auth environment while leaving OpenClaw's OpenAI API key available for embeddings/providers.

A conservative fix might be to expose clearEnv first, so users can opt into:

"clearEnv": ["OPENAI_API_KEY"]

without removing the key globally from OpenClaw.

Related / context

This seems adjacent to the existing routing/auth confusion around native Codex app-server vs openai-codex/* PI/OAuth routes and API-key routes. The key point here is specifically environment inheritance into the native app-server child process.

extent analysis

TL;DR

The most likely fix is to expose plugins.entries.codex.config.appServer.clearEnv in the Codex plugin config schema to prevent the OPENAI_API_KEY environment variable from being inherited by the Codex app-server process.

Guidance

  • Identify the Codex plugin configuration file and check if it allows setting appServer.clearEnv to exclude OPENAI_API_KEY from being passed to the app-server process.
  • Consider modifying the createStdioTransport function to clear OPENAI_API_KEY from the environment variables passed to the app-server process when a ChatGPT/OAuth Codex auth profile is detected.
  • Review the OpenClaw documentation to see if there are any existing configuration options or workarounds for managing environment variables in child processes.

Example

{
  "plugins": {
    "entries": {
      "codex": {
        "config": {
          "appServer": {
            "clearEnv": ["OPENAI_API_KEY"]
          }
        }
      }
    }
  }
}

Notes

This fix assumes that exposing clearEnv in the Codex plugin config schema is a viable solution. However, the feasibility of this approach depends on the underlying implementation of the OpenClaw and Codex plugins.

Recommendation

Apply a workaround by modifying the Codex plugin configuration to exclude OPENAI_API_KEY from being passed to the app-server process, as this is a more targeted and less invasive solution compared to modifying the createStdioTransport function.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

A global OPENAI_API_KEY needed by OpenClaw for embeddings/providers should not automatically force the native Codex app-server into API-key mode when the intended Codex auth profile / local Codex login is ChatGPT/OAuth.

At minimum, there should be a supported way to prevent selected environment variables from being inherited by the Codex app-server process.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Codex app-server inherits OPENAI_API_KEY from gateway and switches to API key mode [1 pull requests, 1 participants]