hermes - ✅(Solved) Fix auth remove openai-codex can re-seed a new device_code credential from ~/.codex/auth.json [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
NousResearch/hermes-agent#12747Fetched 2026-04-20 12:17:09
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Participants

hermes auth remove openai-codex <target> can leave an extra device_code credential behind when ~/.codex/auth.json exists. The removal path calls load_pool(), and load_pool() auto-imports Codex CLI tokens into the Hermes auth store before the target credential is removed.

This means a command that should only delete one pool entry can also mutate ~/.hermes/auth.json by seeding a new singleton entry from the external Codex CLI state.

Root Cause

  1. Removing a label-targeted manual entry still leaves two credentials in the pool (the surviving manual entry + an imported singleton).
  2. Removing target 2 can act on the wrong logical set of credentials because load_pool() has already injected an extra seeded entry into the pool state.

PR fix notes

PR #13330: fix(auth): suppress codex CLI reseed on remove

Description (problem / solution / changelog)

Fixes #12747.

Root cause: hermes auth remove openai-codex suppressed the Hermes device_code source, but the same credentials could still be imported from the Codex CLI shared ~/.codex/auth.json file on the next pool load.

Fix summary:

  • Treat the Codex CLI import as an alias of the OpenAI Codex device-code source for suppression checks.
  • Skip Codex CLI token import while the source is suppressed.
  • Clear both suppression aliases when the user explicitly logs in again.
  • Add regression coverage for direct import, auth remove, manual device-code removal, and re-linking.

Tests:

  • uv run --frozen --python 3.11 --extra dev pytest -o addopts= tests/hermes_cli/test_auth_commands.py tests/hermes_cli/test_auth_codex_provider.py -q
  • git diff --check -- hermes_cli/auth.py tests/hermes_cli/test_auth_codex_provider.py tests/hermes_cli/test_auth_commands.py

Changed files

  • hermes_cli/auth.py (modified, +27/-5)
  • tests/hermes_cli/test_auth_codex_provider.py (modified, +25/-0)
  • tests/hermes_cli/test_auth_commands.py (modified, +13/-0)
RAW_BUFFERClick to expand / collapse

Summary

hermes auth remove openai-codex <target> can leave an extra device_code credential behind when ~/.codex/auth.json exists. The removal path calls load_pool(), and load_pool() auto-imports Codex CLI tokens into the Hermes auth store before the target credential is removed.

This means a command that should only delete one pool entry can also mutate ~/.hermes/auth.json by seeding a new singleton entry from the external Codex CLI state.

Affected files / lines

  • hermes_cli/auth_commands.py:303-315auth_remove_command() resolves the target via load_pool(provider)
  • agent/credential_pool.py:1341-1363load_pool() always runs singleton seeding before removal
  • agent/credential_pool.py:1155-1189_seed_from_singletons() imports ~/.codex/auth.json into providers.openai-codex / credential_pool.openai-codex

Why this is a bug

auth remove is expected to remove exactly the requested credential. Instead, on machines where Codex CLI is logged in, the command can persist a fresh device_code entry that the user did not ask to add.

Two concrete bad outcomes:

  1. Removing a label-targeted manual entry still leaves two credentials in the pool (the surviving manual entry + an imported singleton).
  2. Removing target 2 can act on the wrong logical set of credentials because load_pool() has already injected an extra seeded entry into the pool state.

Minimal reproduction

  1. Create ~/.hermes/auth.json with two manual openai-codex pool entries (work-account, personal-account).
  2. Create ~/.codex/auth.json with a valid Codex access/refresh token pair.
  3. Run hermes auth remove openai-codex personal-account.
  4. Inspect ~/.hermes/auth.json.

Actual behavior

The command prints that it removed personal-account, but the resulting pool still contains:

  • work-account
  • a newly imported device_code entry seeded from ~/.codex/auth.json

I reproduced this locally with a fully isolated temp HERMES_HOME + temp CODEX_HOME; after auth_remove_command(), the pool persisted:

The selected test chunk also reproduces this on default-branch main:

  • pytest -q tests/hermes_cli/test_auth_commands.py ...
  • failing tests:
    • test_auth_remove_accepts_label_target
    • test_auth_remove_prefers_exact_numeric_label_over_index

Expected behavior

auth remove should only remove the requested credential and should not auto-import external Codex CLI credentials as a side effect.

Suggested investigation direction

Possible fix directions:

  • Make auth_remove_command() operate on the persisted pool entries without triggering singleton seeding/import.
  • Or teach load_pool() / _seed_from_singletons() to skip Codex CLI auto-import for destructive management commands like auth remove.
  • At minimum, prevent openai-codex singleton seeding from mutating the pool during target resolution.

extent analysis

TL;DR

The issue can be fixed by modifying the auth_remove_command() to operate on the persisted pool entries without triggering singleton seeding/import or by teaching load_pool() to skip Codex CLI auto-import for destructive management commands.

Guidance

  • Investigate modifying the auth_remove_command() in hermes_cli/auth_commands.py to load the pool without seeding singletons from external sources.
  • Consider adding a flag to load_pool() in agent/credential_pool.py to indicate whether singleton seeding should be performed, and pass this flag from auth_remove_command().
  • Review the _seed_from_singletons() method in agent/credential_pool.py to determine if it can be modified to skip seeding for openai-codex when the command is auth remove.
  • Test the changes with the provided minimal reproduction steps to ensure the issue is resolved.

Example

# hermes_cli/auth_commands.py
def auth_remove_command():
    # ...
    # Load pool without seeding singletons
    pool = load_pool(provider, seed_singletons=False)
    # ...

# agent/credential_pool.py
def load_pool(provider, seed_singletons=True):
    # ...
    if seed_singletons:
        _seed_from_singletons()
    # ...

Notes

The provided fix directions suggest two possible approaches: modifying auth_remove_command() or teaching load_pool() to skip Codex CLI auto-import. The chosen solution should be tested thoroughly to ensure it resolves the issue without introducing new problems.

Recommendation

Apply a workaround by modifying the auth_remove_command() to operate on the persisted pool entries without triggering singleton seeding/import. This approach seems to be the most straightforward and least invasive solution.

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

auth remove should only remove the requested credential and should not auto-import external Codex CLI credentials as a side effect.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING