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
-
Check out current dev and install the frozen dependency tree:
git checkout dev
git pull --ff-only origin dev
bun install --frozen-lockfile
-
Create one temporary CODEX_HOME/auth.json containing an expired access token and a valid refresh token.
-
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.
-
Observe that the existing pool-lock namespace does not serialize the two processes by canonical Codex home.
-
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.
-
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
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 replacesauth.jsonbetween the final check and rename can still be overwritten. Native-main refresh also reuses the pool refresh lock underOPENCODEX_HOME; two OpenCodex instances with differentOPENCODEX_HOMEvalues but the same canonicalCODEX_HOMEtherefore 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 canonicalauth.jsontarget during publication.Reproduction
Check out current
devand install the frozen dependency tree:Create one temporary
CODEX_HOME/auth.jsoncontaining an expired access token and a valid refresh token.Start two child processes with that same
CODEX_HOMEand distinctOPENCODEX_HOMEdirectories. Have both request native-main refresh while counting OAuth refresh callbacks.Observe that the existing pool-lock namespace does not serialize the two processes by canonical Codex home.
At the existing final pre-rename test hook in
src/codex/main-account.ts, atomically replaceauth.jsonfrom a simulated Codex writer. Resume the native-main publisher.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.tsThe test asserts one physical refresh across different
OPENCODEX_HOMEvalues, byte-for-byte preservation of an external writer, process-death recovery, and stable canonical target presence.Version
devat9cd4e4b8efc055ec8c8f7f9fd76d7c556a065fa6Operating 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.5Logs or error output
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