mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix(auth): refuse to touch real auth.json during pytest; delete sandbox-escaping test (#14729)
A test in tests/agent/test_credential_pool.py (test_try_refresh_current_updates_only_current_entry) monkeypatched refresh_codex_oauth_pure() to return the literal fixture strings 'access-new'/'refresh-new', then executed the real production code path in agent/credential_pool.py::try_refresh_current which calls _sync_device_code_entry_to_auth_store → _save_provider_state → writes to `providers.openai-codex.tokens`. That writer resolves the target via get_hermes_home()/auth.json. If the test ran with HERMES_HOME unset (direct pytest invocation, IDE runner bypassing conftest discovery, or any other sandbox escape), it would overwrite the real user's auth store with the fixture strings. Observed in the wild: Teknium's ~/.hermes/auth.json providers.openai-codex.tokens held 'access-new'/'refresh-new' for five days. His CLI kept working because the credential_pool entries still held real JWTs, but `hermes model`'s live discovery path (which reads via resolve_codex_runtime_credentials → _read_codex_tokens → providers.tokens) was silently 401-ing. Fixes: - Delete test_try_refresh_current_updates_only_current_entry. It was the only test that exercised a writer hitting providers.openai-codex.tokens with literal stub tokens. The entry-level rotation behavior it asserted is still covered by test_mark_exhausted_and_rotate_persists_status above. - Add a seat belt in hermes_cli.auth._auth_file_path(): if PYTEST_CURRENT_TEST is set AND the resolved path equals the real ~/.hermes/auth.json, raise with a clear message. In production (no PYTEST_CURRENT_TEST), a single dict lookup. Any future test that forgets to monkeypatch HERMES_HOME fails loudly instead of corrupting the user's credentials. Validation: - production (no PYTEST_CURRENT_TEST): returns real path, unchanged behavior - pytest + HERMES_HOME unset (points at real home): raises with message - pytest + HERMES_HOME=/tmp/...: returns tmp path, tests pass normally
This commit is contained in:
parent
255ba5bf26
commit
b5333abc30
2 changed files with 19 additions and 61 deletions
|
|
@ -333,66 +333,6 @@ def test_mark_exhausted_and_rotate_persists_status(tmp_path, monkeypatch):
|
|||
assert persisted["last_error_code"] == 402
|
||||
|
||||
|
||||
def test_try_refresh_current_updates_only_current_entry(tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes"))
|
||||
_write_auth_store(
|
||||
tmp_path,
|
||||
{
|
||||
"version": 1,
|
||||
"credential_pool": {
|
||||
"openai-codex": [
|
||||
{
|
||||
"id": "cred-1",
|
||||
"label": "primary",
|
||||
"auth_type": "oauth",
|
||||
"priority": 0,
|
||||
"source": "device_code",
|
||||
"access_token": "access-old",
|
||||
"refresh_token": "refresh-old",
|
||||
"base_url": "https://chatgpt.com/backend-api/codex",
|
||||
},
|
||||
{
|
||||
"id": "cred-2",
|
||||
"label": "secondary",
|
||||
"auth_type": "oauth",
|
||||
"priority": 1,
|
||||
"source": "device_code",
|
||||
"access_token": "access-other",
|
||||
"refresh_token": "refresh-other",
|
||||
"base_url": "https://chatgpt.com/backend-api/codex",
|
||||
},
|
||||
]
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
from agent.credential_pool import load_pool
|
||||
|
||||
monkeypatch.setattr(
|
||||
"hermes_cli.auth.refresh_codex_oauth_pure",
|
||||
lambda access_token, refresh_token, timeout_seconds=20.0: {
|
||||
"access_token": "access-new",
|
||||
"refresh_token": "refresh-new",
|
||||
},
|
||||
)
|
||||
|
||||
pool = load_pool("openai-codex")
|
||||
current = pool.select()
|
||||
assert current.id == "cred-1"
|
||||
|
||||
refreshed = pool.try_refresh_current()
|
||||
|
||||
assert refreshed is not None
|
||||
assert refreshed.access_token == "access-new"
|
||||
|
||||
auth_payload = json.loads((tmp_path / "hermes" / "auth.json").read_text())
|
||||
primary, secondary = auth_payload["credential_pool"]["openai-codex"]
|
||||
assert primary["access_token"] == "access-new"
|
||||
assert primary["refresh_token"] == "refresh-new"
|
||||
assert secondary["access_token"] == "access-other"
|
||||
assert secondary["refresh_token"] == "refresh-other"
|
||||
|
||||
|
||||
def test_load_pool_seeds_env_api_key(tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes"))
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "sk-or-seeded")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue