Blog

Codex CLI Behind a Corporate Network: CA Bundles, Credential Stores, and Login

On a managed network, Codex CLI sign-in failures are usually not about the key. The order to check is trust first, credential storage second, login path third.

Codex CLI Behind a Corporate Network: CA Bundles, Credential Stores, and Login

Codex CLI behind a corporate proxy or inside an inspected network is its own category of setup problems. When sign-in fails, the reflex is to suspect the key or the account, but on managed networks the three most common causes are different: the certificate chain is not trusted because a corporate TLS proxy or a private root certificate sits in the path, the credential storage the CLI depends on has been locked down or enforced by an administrator, or the login path itself is blocked because the browser callback cannot reach the machine. Each has a different fix, and there is a working order to check them: trust first, storage second, login path third. The personal-machine counterpart covers login modes and local credential storage; this one is about the enterprise context.

A codex cli login certificate error: why trust problems wear a login costume

The symptom teams report is usually "login is broken": the CLI stalls at authentication, a handshake fails, or a request that worked yesterday stops completing. Certificate-chain problems often present exactly like that, and the printed error does not always name the trust store as the root cause. That is why the first move on a managed network is not to check the key but to ask whether the machine can complete TLS to the endpoint at all under the organization's interception setup. A TLS proxy re-signs traffic with the organization's own root certificate; tools that carry their own CA trust configuration need that root presented to them explicitly. Codex CLI supports exactly that, and it makes the certificate question cheap to rule in or out before you spend time on credentials.

The trusted CA bundle: set CODEX_CA_CERTIFICATE before login

The official authentication documentation states the setup plainly. If your network uses a corporate TLS proxy or a private root CA, set CODEX_CA_CERTIFICATE to a PEM bundle before logging in:

export CODEX_CA_CERTIFICATE=/path/to/corporate-root-ca.pem
codex login

Three details from the docs matter operationally:

  1. Precedence. CODEX_CA_CERTIFICATE takes precedence over SSL_CERT_FILE. When it is unset, Codex falls back to SSL_CERT_FILE, so environments that already standardize on that variable keep working, but the Codex-specific variable wins when both are present.
  2. Scope. The same custom CA settings apply to login, normal HTTPS requests, and secure WebSocket connections. That matters because a bundle set only for login would leave the working session exposed to the same failures later.
  3. Order. Set it before logging in. The bundle has to be in the environment of the login process itself, which is the part that trips up teams who configure it in a shell profile that interactive logins and service processes do not both inherit.

For the complete environment-variable behavior, see the authentication documentation.

Credential storage: the four cli_auth_credentials_store modes

Where the CLI keeps cached credentials is a configuration decision, and on managed machines it overlaps with corporate policy. The cli_auth_credentials_store setting accepts four values:

  • file stores credentials in auth.json under CODEX_HOME, which defaults to ~/.codex.
  • keyring stores credentials in the operating system credential store, and fails if that store is unavailable. This is the mode managed fleets reach for, but verify the store actually exists in your environment before enforcing it.
  • auto uses the OS credential store when available and otherwise falls back to auth.json, which makes it the accommodating choice for mixed environments.
  • ephemeral keeps credentials in memory only for the current process, which fits containers and one-shot tasks where nothing should persist to disk.

Two consequences follow. First, if the store is set to file, treat ~/.codex/auth.json like a password: it contains access tokens, so it must not be committed, pasted into tickets, or shared in chat. Second, the choice is not always yours to make: administrators can enforce both the credential store and the ChatGPT base URL through local authentication requirements, and users cannot override those requirements through config.toml or CLI overrides.

Whichever mode you choose, the credential itself still follows the key lifecycle rules: an expiry date, a rotation path, and a revocation path, as the key hygiene guide lays out.

When administrators enforce the settings

This is the section to read when "I changed it and nothing happened." The managed configuration documentation explains that administrators set cli_auth_credentials_store and chatgpt_base_url (alongside login-method and workspace restrictions) in the local system requirements file or through macOS MDM requirements. Two properties of these local requirements explain most of the confusion:

  • They apply before credentials load and before Codex retrieves cloud policy, so the enforced value is in effect by the time anything else looks at configuration.
  • The cloud-managed side ignores these particular fields; local enforcement is the mechanism.

If a worker machine rejects a credential store mode that works on a colleague's laptop, the answer is usually not in config.toml at all. It is in the requirements file the administrator controls, and the fix is a conversation with that administrator, not a config edit.

Shared cache, shared surprises

Codex caches login details and reuses them across surfaces: the ChatGPT desktop app, the CLI, and the IDE extension all participate in one caching story, and the CLI and extension specifically share the same cached login details. If someone logs out from either one, the next start of the CLI or extension requires signing in again. The details live locally in a plaintext file at ~/.codex/auth.json or in the OS-specific credential store, depending on the mode; and for ChatGPT sign-in sessions, Codex refreshes tokens automatically during use before they expire, so active sessions usually continue without another browser trip.

The engineering takeaway: "it works on my machine but not theirs" is an expected class of problem on fleets, and the variables to compare are concrete: which credential store is available on that machine, which mode is enforced there, and what state the per-user cache is in. That comparison is faster than any reinstall.

Choosing a login path on a locked network

The browser-based login flow has two documented failure conditions that enterprises hit constantly: running the CLI in a remote or headless environment, and local networking that blocks the localhost callback Codex uses to return the OAuth token after sign-in. In these situations the docs say to prefer device code authentication (beta): choose Sign in with Device Code in the interactive login UI, or run codex login --device-auth directly.

One prerequisite matters and it is organizational, not technical: device code login must be enabled first, in ChatGPT security settings for a personal account or in workspace permissions by an administrator. That enablement point is the same one described in the earlier credentials guide, and on managed networks it is often the difference between a five-minute setup and a support ticket. If device code authentication is not available in your environment, the official documentation describes fallback methods for getting a login onto the machine, and direct codex login runs write a dedicated codex-login.log under the configured log directory that is the right artifact to bring to that conversation, especially for browser-login and device-code failures.

Non-interactive credentials for automation

Automation uses different credentials than interactive login, and the distinction is worth keeping sharp:

  • CODEX_API_KEY provides an API key to a non-interactive Codex process. The documented deployment advice: set it inline rather than job-wide when running repository-controlled code, so that code executing in the job cannot read the credential out of the environment.
  • CODEX_ACCESS_TOKEN provides a ChatGPT or Codex access token for trusted automation; for a persisted login, pipe it to codex login --with-access-token. The access tokens documentation covers provisioning.
  • Workload identity covers the third pattern, where the process environment supplies identity: OPENAI_FEDERATION_RULE_ID selects the federation rule configured for the workload, OPENAI_IDENTITY_TOKEN_FILE points to the absolute path of the file that contains the current OIDC token or SPIFFE JWT-SVID, and OPENAI_WORKLOAD_IDENTITY_CONTEXT optionally supplies bounded JSON identifiers for client-reported audit attribution, without affecting authentication or authorization. When workload identity is selected, codex login and codex logout are rejected, because the process environment controls authentication.

One boundary to keep in mind: a model provider's API key is not a CLI credential. For provider keys, Codex reads the variable named by env_key in the model provider configuration, so the variable name itself is not fixed. CI-specific patterns for these credentials live in the coding agents in CI guide.

The troubleshooting order

On a managed network, work the layers in this order:

  1. Trust. Is CODEX_CA_CERTIFICATE set to the corporate PEM bundle, in the environment that runs the login process, with SSL_CERT_FILE as the documented fallback? This comes first because its symptoms mimic everything else.
  2. Storage. Which cli_auth_credentials_store mode is in effect, is the underlying store actually available on this machine, and is the mode enforced by local requirements you cannot override?
  3. Login path. Can the browser flow complete (callback reachable), or is device code the right route? Keep codex-login.log as evidence when it fails.
  4. Application layer. If authentication succeeds and requests still fail, the problem has moved: region and permission denials have their own classification in the 403 guide, and the general status-code triage lives in the error code guide.

One more failure that masquerades as a setup problem: a pinned model that has been retired, so check the October 2026 shutdown roundup against your model ID.

The checklist

  1. Set CODEX_CA_CERTIFICATE to the PEM bundle before login when TLS interception is present; remember the SSL_CERT_FILE fallback and the login, HTTPS, and WebSocket scope.
  2. Verify the variable reaches the actual login process, not just an interactive shell.
  3. Choose the credential store deliberately: keyring for managed machines that have one, ephemeral for containers, auto for mixed environments.
  4. Treat auth.json as a password whenever file storage is in play.
  5. When a setting will not take effect, suspect the local requirements file before suspecting the CLI.
  6. For headless or callback-blocked hosts, enable and use device code authentication; keep codex-login.log from failures.
  7. For automation, pick the right credential class: CODEX_API_KEY inline, CODEX_ACCESS_TOKEN for trusted pipelines, workload identity where the platform issues identity.
  8. For "works for me, not for them," compare certificate bundle, credential store availability, enforced configuration, and callback reachability on both machines.

Enterprise environments reward exactly one habit: checking trust before credentials, and credentials before code. The endpoint-level facts for whatever endpoint your team calls live in the platform's own documentation.