fix(auth): openai-codex multi-profile rotation write-through (#48415) - #49032
Closed
ochsec wants to merge 3 commits into
Closed
fix(auth): openai-codex multi-profile rotation write-through (#48415)#49032ochsec wants to merge 3 commits into
ochsec wants to merge 3 commits into
Conversation
added 3 commits
June 18, 2026 13:22
When a profile session reads the openai-codex grant from the root fallback and refreshes it, the rotated refresh token was saved only to the profile store. The root kept the now-revoked refresh token, so every sibling profile reading root's stale grant died with refresh_token_reused. This mirrors the xAI OAuth write-through pattern (#43589) for Codex: - Add _profile_has_own_codex_state() helper (mirrors _profile_has_own_xai_oauth_state) - Add _write_through_codex_to_global_root() helper (mirrors _write_through_xai_oauth_to_global_root) - Wire write-through into _save_codex_tokens() in auth.py - Wire write-through into CredentialPool._sync_device_code_entry_to_auth_store() in credential_pool.py - Check BEFORE modifying auth_store so the profile doesn't look like it has its own block - Use set_active=False to avoid flipping root's active_provider Also fixes a pre-existing gap: the xAI branch in _sync_device_code_entry_to_auth_store() was missing the write-through check that auth.py's _save_xai_oauth_tokens() already had. Added it for parity. Tests: 5 new regression tests covering write-through, no-write-when-shadow, classic-mode noop, failure isolation, and active_provider preservation.
egilewski
suggested changes
Jun 19, 2026
egilewski
left a comment
Contributor
There was a problem hiding this comment.
requesting changes
Blocking checks:
- The PR is not focused on a single reviewable change. Its title/body and auth commit cover
openai-codexOAuth token write-through, but the same PR head also includes unrelated kanban blocked-task behavior from commit7d7801347and changeshermes_cli/kanban_db.pyplustests/hermes_cli/test_kanban_blocked_sticky.py. - Reproduce with
gh pr diff 49032 --repo NousResearch/hermes-agent --name-onlyandgh pr view 49032 --repo NousResearch/hermes-agent --json commits --jq '.commits[].messageHeadline'.
Security evidence:
- trust boundary: profile/root OAuth credential state for
openai-codex; review stopped before validating it because unrelated kanban behavior is bundled. - source/sink/invariant: security PRs need a focused diff so auth-token rotation changes can be reviewed and tested without unrelated task-dispatch behavior.
- current-main reproduction: current
mainwas refreshed to1b04e4ede5199102f54393abec8e128ddd994645;git merge-tree --write-tree refs/remotes/security-review-49032/main refs/remotes/security-review-49032/prsucceeded, so this is not a merge-conflict stop. - PR-head or patch-replay validation: PR head
2491a21781bcc79e573858e9e74684c08b3d9c2bincludes both auth files/tests and kanban files/tests; the no-merge commit list includes2491a2178for auth and7d7801347for kanban. - positive/negative cases: auth regression tests are present, but the unrelated kanban code/test pair makes focused security validation premature.
- residual bypass search: not run; review stopped at the first serious PR-shape blocker, so there may be additional issues.
Please split the kanban change out or retarget this PR to only the auth write-through fix, then request another review.
Signed: GPT-5.5-xhigh in Codex
Author
|
Closing in favor of #49127 — this branch contained unrelated kanban commits that were included in the PR diff. The new PR has a clean branch based on upstream/main with only the auth write-through changes. |
14 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a profile session reads the
openai-codexgrant from the root fallback and refreshes it, the rotated refresh token was saved only to the profile store. The root kept the now-revoked refresh token, so every sibling profile reading root's stale grant died withrefresh_token_reusedonce their access token expired.This is the Codex analog of #43589 (which fixed the same hazard for
xai-oauth).Fix
Mirrors the existing xAI OAuth write-through pattern for the
openai-codexprovider:_profile_has_own_codex_state()— new helper, mirrors_profile_has_own_xai_oauth_state(). ReturnsTruewhen the profile has its ownproviders.openai-codexblock (meaning it genuinely shadows root and must not clobber it)._write_through_codex_to_global_root()— new helper, mirrors_write_through_xai_oauth_to_global_root(). Best-effort write of the rotated state to the global root auth.json. Swallows all errors — a failed write-through degrades to the pre-existing behavior (root stale), it must never break the profile's own successful save._save_codex_tokens()— check_profile_has_own_codex_state()before modifyingauth_store, then conditionally call_write_through_codex_to_global_root()after the profile save.CredentialPool._sync_device_code_entry_to_auth_store()— wire the same write-through check for theopenai-codexbranch. Also adds the missing write-through for thexai-oauthbranch (this was a pre-existing gap — the pool-sync path was not covered by Bug: profile auth shadowing + rotating refresh tokens guarantees grant revocation on multi-profile installs #43589).Key design details
_profile_has_own_codex_statecheck happens before_save_provider_statemodifiesauth_store, because after the save the profile would always appear to have its own block._store_provider_state(global_store, ..., set_active=False)ensures we never flip root'sactive_provider._write_through_codex_to_global_rootrefuses to write the real user's~/.hermes/auth.jsonunder test.Tests
5 new regression tests in
tests/hermes_cli/test_codex_oauth_writethrough.py:_global_auth_file_path()returnsNoneactive_providerpreserved — write-through does not flip root's active providerAll existing xAI write-through tests continue to pass.
Files changed
hermes_cli/auth.py_profile_has_own_codex_state, +_write_through_codex_to_global_root, wire into_save_codex_tokensagent/credential_pool.pyopenai-codexandxai-oauthbranches in_sync_device_code_entry_to_auth_storetests/hermes_cli/test_codex_oauth_writethrough.py