Files
bot-bottle/docs/prds/0029-codex-host-credentials-egress.md
T

6.5 KiB

PRD 0029: Codex host credentials through egress

  • Status: Draft
  • Author: didericis-codex
  • Created: 2026-05-29
  • Issue: #109

Summary

Allow Codex bottles to use a host-authorized ChatGPT/device-login access token by forwarding it only into the egress sidecar, gated by an explicit agent_provider.forward_host_credentials manifest flag.

Problem

Codex bottles can reach OpenAI hosts after they are added to egress, but requests to Codex's ChatGPT-backed API endpoints still fail with HTTP 403 when the egress route is unauthenticated. The egress proxy strips agent-originated Authorization headers and only re-injects auth for routes that declare an egress-owned token. Bare api.openai.com or chatgpt.com routes therefore forward Codex requests without the ChatGPT bearer token.

Copying ~/.codex/auth.json into the agent would solve auth but would also put access and refresh material inside the agent sandbox. That cuts against bot-bottle's credential minimization model: provider credentials should live in the sidecar boundary when possible, not in the agent.

Goals / Success Criteria

  • A Codex bottle with host ChatGPT auth can call Codex's api.openai.com and chatgpt.com endpoints through egress.
  • Host credential forwarding happens only when the bottle declares agent_provider.forward_host_credentials: true.
  • The agent container does not receive OPENAI_API_KEY, CODEX_ACCESS_TOKEN, tokens.access_token, tokens.refresh_token, or auth.json.
  • Egress route files remain non-secret: they contain only host/path/auth slot metadata, never token values.
  • Missing, non-ChatGPT, malformed, or expired host Codex auth fails launch with a clear operator-facing message.
  • Existing Claude OAuth placeholder behavior remains unchanged.

Non-goals

  • Refreshing Codex tokens in the sidecar. The first cut reads the host's current access token at launch; operators can restart after host Codex refreshes auth.
  • Copying host ~/.codex/auth.json into the agent.
  • Allowing arbitrary host credential forwarding. This PRD covers Codex ChatGPT/device-login credentials only.
  • Hot-applying new authenticated Codex routes to an existing running sidecar. The current hot-apply path cannot safely populate new token env slots in an already-running container.

Scope

In scope

  • Add agent_provider.forward_host_credentials to the bottle manifest schema, defaulting to false.
  • Support the flag for agent_provider.template: codex.
  • Read host Codex auth from $CODEX_HOME/auth.json when CODEX_HOME is set, otherwise from ~/.codex/auth.json.
  • Extract only tokens.access_token.
  • Validate that auth_mode is chatgpt and the access token is present, JWT-shaped, and not expired.
  • Add or upgrade api.openai.com and chatgpt.com egress routes to inject that access token via a shared EGRESS_TOKEN_N sidecar env slot.
  • Pass the extracted token only into the sidecar compose/run environment, alongside other egress token values.

Out of scope

  • Sidecar-owned refresh using tokens.refresh_token.
  • Sharing full Codex auth state with the agent.
  • Supporting host credential forwarding for non-Codex providers.

Design

Manifest

Extend agent_provider:

agent_provider:
  template: codex
  forward_host_credentials: true

The field defaults to false. If set on a non-Codex provider, manifest validation should reject it until that provider has a concrete, credential-minimizing implementation.

Host auth extraction

At prepare/launch time, when the flag is enabled for Codex:

  1. Resolve the host Codex home directory from $CODEX_HOME, falling back to ~/.codex.
  2. Parse auth.json.
  3. Require auth_mode == "chatgpt".
  4. Require a non-empty tokens.access_token.
  5. Parse the JWT payload enough to require an exp claim in the future.
  6. Return only the access token value to the launch path.

Errors should name the missing or invalid condition and point the operator at codex login --device-auth, without printing token values.

Egress route

When forwarding host Codex credentials, the effective egress route table should contain authenticated api.openai.com and chatgpt.com routes. If the bottle already declares either host as a bare-pass route, upgrade it in the effective route table rather than requiring a duplicate manifest entry. If the bottle already declares an authenticated route for either host, fail rather than guessing whether to override operator-provided auth, unless that route already uses the synthetic Codex host credential token reference.

The rendered route should look like any other egress-owned auth route:

routes:
  - host: "api.openai.com"
    auth_scheme: "Bearer"
    token_env: "EGRESS_TOKEN_N"
  - host: "chatgpt.com"
    auth_scheme: "Bearer"
    token_env: "EGRESS_TOKEN_N"

The access token value is supplied through the sidecar process environment for that EGRESS_TOKEN_N slot. It must not be written to routes.yaml, compose files, env files, logs, or user-facing output.

Data flow

flowchart LR
    H["Host ~/.codex/auth.json"] --> L["bot-bottle launch"]
    L -->|access token only| S["egress sidecar env"]
    A["Codex agent"] -->|HTTPS via proxy, auth stripped| E["egress"]
    E -->|Bearer injected from env| C["api.openai.com / chatgpt.com"]

Implementation chunks

  1. PRD first. Land this document as the first commit on the feature branch.
  2. Manifest schema. Add forward_host_credentials, validation, and unit tests.
  3. Host Codex auth reader. Add a small stdlib-only helper for parsing and validating host Codex auth without printing values.
  4. Effective egress route. Add/upgrade the Codex API routes when the flag is enabled, and add tests for bare route upgrade, missing-route insertion, and authenticated-route conflict.
  5. Launch wiring. Pass the host access token into the egress sidecar env for Docker and smolmachines without exposing it to the agent.
  6. Docs and tests. Update README examples and run the unit suite.

Open questions

  • Should a later version support sidecar refresh using the host refresh token, or should restart-on-expiry remain the policy?
  • Should telemetry hosts such as ab.chatgpt.com stay blocked by default even when Codex ChatGPT auth is enabled?

References

  • Gitea issue #109: Codex ChatGPT auth should inject host access token via egress.
  • PRD 0017: Egress-proxy — universal MITM with path filtering + auth injection.
  • PRD 0026: Agent provider templates.