fix(codex): forward host credentials to api route

This commit is contained in:
2026-05-29 03:34:11 -04:00
committed by didericis
parent 711cb9c194
commit 62dd7b2aa5
4 changed files with 89 additions and 40 deletions
+28 -21
View File
@@ -13,12 +13,13 @@ explicit `agent_provider.forward_host_credentials` manifest flag.
## Problem
Codex bottles can reach `chatgpt.com` after the host is added to egress,
but requests to `chatgpt.com/backend-api/codex/...` still fail with
HTTP 403. The egress proxy strips agent-originated `Authorization`
headers and only re-injects auth for routes that declare an egress-owned
token. A bare `chatgpt.com` route therefore forwards Codex requests
without the ChatGPT bearer token.
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
@@ -27,8 +28,8 @@ should live in the sidecar boundary when possible, not in the agent.
## Goals / Success Criteria
- A Codex bottle with host ChatGPT auth can call
`chatgpt.com/backend-api/codex/...` through egress.
- 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`,
@@ -48,9 +49,9 @@ should live in the sidecar boundary when possible, not in the agent.
- Copying host `~/.codex/auth.json` into the agent.
- Allowing arbitrary host credential forwarding. This PRD covers Codex
ChatGPT/device-login credentials only.
- Hot-applying a new authenticated `chatgpt.com` route to an existing
running sidecar. The current hot-apply path cannot safely populate new
token env slots in an already-running container.
- 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
@@ -64,8 +65,9 @@ should live in the sidecar boundary when possible, not in the agent.
- 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 a `chatgpt.com` egress route to inject that access token
via an `EGRESS_TOKEN_N` sidecar env slot.
- 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.
@@ -109,16 +111,21 @@ operator at `codex login --device-auth`, without printing token values.
### Egress route
When forwarding host Codex credentials, the effective egress route table
should contain an authenticated `chatgpt.com` route. If the bottle
already declares `chatgpt.com` 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 `chatgpt.com` route,
fail rather than guessing whether to override operator-provided auth.
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:
```yaml
routes:
- host: "api.openai.com"
auth_scheme: "Bearer"
token_env: "EGRESS_TOKEN_N"
- host: "chatgpt.com"
auth_scheme: "Bearer"
token_env: "EGRESS_TOKEN_N"
@@ -135,7 +142,7 @@ 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["chatgpt.com"]
E -->|Bearer injected from env| C["api.openai.com / chatgpt.com"]
```
## Implementation chunks
@@ -146,8 +153,8 @@ flowchart LR
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 `chatgpt.com` route when
the flag is enabled, and add tests for bare route upgrade,
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.