feat(proxy): add authenticated OpenAI Codex upstream - #62510
Conversation
Independent review follow-upA separate read-only reviewer audited the staged changes after implementation. Verdict: no blocking security, correctness, or compatibility issues. Verified by the reviewer:
Non-blocking note: bracketed or DNS loopback aliases are conservatively treated as non-loopback and therefore require a token file. This is intentionally safer than broad alias recognition, so no change was made. |
Related: competing open implementation alongside #54877 and #62297 — all three add an |
|
All local tests and live authenticated Luna canaries pass. The author has requested immediate merge; this PR is mergeable but branch protection requires a maintainer with merge permission. |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for extending the existing proxy-adapter surface; current main still has no Codex proxy adapter (hermes_cli/proxy/adapters/__init__.py:16-19).
Problems
hermes_cli/proxy/adapters/openai_codex.py:59cannot refresh a pool-only Codex credential after a 401. The resolver's pool fallback returns directly athermes_cli/auth.py:3652-3666without usingforce_refresh; the next line suppresses retry if that unchanged bearer is returned. The existing pool API providestry_refresh_current()(agent/credential_pool.py:1610-1621), and the xAI adapter uses that recovery pattern (hermes_cli/proxy/adapters/xai.py:76-109).hermes_cli/proxy/cli.py:25reads any path without checking file type or POSIX permissions, although the PR's security boundary relies on a mode-0600 downstream token file before allowing non-loopback binds.- The public proxy docs remain inconsistent with the new CLI behavior:
website/docs/user-guide/features/subscription-proxy.md:167-174documents unauthenticated LAN startup, andwebsite/docs/reference/cli-commands.md:463omits both Codex and--auth-token-file.
Suggested changes
- Route pool-backed Codex recovery through selected-entry refresh/rotation and add a pool-only 401 regression test.
- Reject insecure token files on POSIX and cover that failure mode.
- Update both proxy documentation surfaces.
Automated hermes-sweeper review.
| return None | ||
| with self._lock: | ||
| refreshed = self._resolve_credential(force_refresh=True) | ||
| if refreshed.bearer == failed_credential.bearer: |
There was a problem hiding this comment.
This cannot force-refresh a pool-only Codex credential: resolve_codex_runtime_credentials() returns directly from its pool fallback at hermes_cli/auth.py:3652-3666 without using force_refresh, so the unchanged bearer is rejected on the next line and no retry occurs. Select and refresh the pool entry here (as the xAI adapter does), and add a pool-only 401 regression test.
|
|
||
| def _read_downstream_token_file(path: str) -> str: | ||
| token_path = Path(path).expanduser() | ||
| token = token_path.read_text(encoding="utf-8").strip() |
There was a problem hiding this comment.
For a non-loopback bind, this accepts a token from any readable path, including a world-readable file or symlink. That does not enforce the stated mode-0600 security boundary. Validate a regular owner-only file on POSIX before allowing the bind, with an insecure-mode rejection test.
|
Follow-up containment fix added in 4830198 after live monitoring found gateway-internal subagent/compaction traffic reaching Honcho. The fix enforces the existing saveMessages=false hard gate in sync_turn, drops anchored internal gateway notifications, and refuses empty sanitized turns. Validation: 422 targeted Honcho/proxy tests passed; Ruff and git diff checks passed. |
Summary
openai-codexupstream adapter to the local OpenAI-compatible proxy--auth-token-fileis configuredSecurity boundary
The downstream bearer is read from a file and compared in constant time. The downstream
Authorizationheader is never forwarded to Codex; it is replaced with the refreshed upstream OAuth credential. Required provider headers override downstream-supplied values.Validation
scripts/run_tests.sh tests/hermes_cli/test_proxy.py— 48 passedruff check hermes_cli/proxy hermes_cli/subcommands/gateway.py tests/hermes_cli/test_proxy.py— passed/v1/responsesreturned401 proxy_auth_failedLAUNCHD_OKOpenAI Codex OAuthupstreamDeployment note
This PR does not add or store any OAuth credential or downstream token in the repository. Runtime secrets remain outside Git in a mode-0600 token file and Hermes's existing credential store.