Skip to content

[Bug]: Native-main refresh publication can overwrite external Codex writers #2999

Description

@MarcTCruz

Client or integration

Codex CLI

Area

Authentication and account pool

Summary

Current dev (9cd4e4b8efc055ec8c8f7f9fd76d7c556a065fa6) contains the native-main refresh implementation merged for #2221, but its publication and coordination protocol still has two credential-safety races.

The publisher hashes auth.json, checks it again, and then renames a staged file over it. A Codex writer that replaces auth.json between the final check and rename can still be overwritten. Native-main refresh also reuses the pool refresh lock under OPENCODEX_HOME; two OpenCodex instances with different OPENCODEX_HOME values but the same canonical CODEX_HOME therefore do not coordinate the file they both write.

Expected behavior: native-main refresh coordinates by canonical CODEX_HOME, preserves an external writer atomically, recovers deterministically after process death, and never removes the canonical auth.json target during publication.

Reproduction

  1. Check out current dev and install the frozen dependency tree:

    git checkout dev
    git pull --ff-only origin dev
    bun install --frozen-lockfile
  2. Create one temporary CODEX_HOME/auth.json containing an expired access token and a valid refresh token.

  3. Start two child processes with that same CODEX_HOME and distinct OPENCODEX_HOME directories. Have both request native-main refresh while counting OAuth refresh callbacks.

  4. Observe that the existing pool-lock namespace does not serialize the two processes by canonical Codex home.

  5. At the existing final pre-rename test hook in src/codex/main-account.ts, atomically replace auth.json from a simulated Codex writer. Resume the native-main publisher.

  6. Observe that the staged credential can overwrite the external writer after the last hash check.

A deterministic regression is included in the linked fix branch:

./node_modules/bun/bin/bun.exe test --preload ./tests/preload.ts \
  tests/atomic-file-preserving-replace.test.ts \
  tests/codex-main-account-refresh.test.ts \
  tests/native-main-refresh-process.test.ts

The test asserts one physical refresh across different OPENCODEX_HOME values, byte-for-byte preservation of an external writer, process-death recovery, and stable canonical target presence.

Version

dev at 9cd4e4b8efc055ec8c8f7f9fd76d7c556a065fa6

Operating system

Ubuntu 24.04 (Linux 6.8); macOS and Windows replacement adapters require CI runtime coverage

Provider and model

OpenAI native main account / gpt-5.5

Logs or error output

No token values are logged. The failure is observed as either more than one refresh callback for one CODEX_HOME or an auth.json SHA-256 different from the external writer's expected SHA-256.

Screenshots and supporting files

Not applicable. The linked regression uses temporary homes, child processes, SHA-256 identities, and loopback-only fixtures.

Redacted configuration

{
  "CODEX_HOME": "/tmp/ocx-native-main-repro/codex",
  "OPENCODEX_HOME_A": "/tmp/ocx-native-main-repro/ocx-a",
  "OPENCODEX_HOME_B": "/tmp/ocx-native-main-repro/ocx-b"
}

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Metadata

Metadata

Assignees

No one assigned

    Labels

    account-poolOAuth, credentials, Codex pool, quota, failover, plansbugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions