-
Notifications
You must be signed in to change notification settings - Fork 15
Description
Summary
The AWF api-proxy cannot obtain a Copilot session token on GitHub Enterprise Cloud with data residency instances. The proxy's token exchange calls /copilot_internal/v2/token which returns 403 on data residency, causing the Copilot CLI inside the container to get 400 Bad Request when listing models — and immediately exit with code 1.
The Copilot CLI works perfectly when run directly on the host (bypassing the api-proxy), proving that Copilot itself is fully functional on data residency. The issue is exclusively in the api-proxy's token exchange mechanism.
Environment
- Platform: GHE Cloud with data residency (EU)
- Domain:
contoso-aw.ghe.com/api.contoso-aw.ghe.com - gh-aw version: v0.59.0
- AWF version: v0.24.2
- Copilot CLI: 1.0.6
- Workflow:
repo-assist(fromgithubnext/agentics) - Copilot license: Enterprise plan, CLI enabled, seat assigned to user
Reproduction
- Set up a repo on a GHE Cloud data residency instance
- Configure
api-target: "api.contoso-aw.ghe.com"in workflow frontmatter - Create a fine-grained PAT with Copilot Requests: Read-only permission
- Run the workflow — agent step fails immediately (5 seconds, exit code 1)
Evidence
Inside AWF container (FAILS) — run 22234276
From sandbox/agent/logs/process-*.log:
Using COPILOT_API_URL from environment: http://172.30.0.30:10002
No auth info available, skipping custom agents load
Starting Copilot CLI: 1.0.6
Error loading models: Error: Failed to list models: 400 Bad Request
MCP transport for github closed
MCP client for github closed
runPromptMode: executePromptDirectly returned succeeded=false
runPromptMode: exiting with code 1
The CLI connects to the api-proxy at 172.30.0.30:10002, which returns 400 because it failed its own upstream token exchange.
Outside AWF container (WORKS) — same run, diagnostic step
executePromptDirectly completing: hasError=false, will return true
runPromptMode: executePromptDirectly returned succeeded=true
runPromptMode: exiting with code 0
[shutdown] Shutdown complete
The same Copilot CLI binary, same token, same host — but running directly on the runner (not through the api-proxy) — authenticates and completes successfully.
Token exchange curl test (confirms proxy root cause)
curl -H "Authorization: token <COPILOT_GITHUB_TOKEN>" \
"https://api.contoso-aw.ghe.com/copilot_internal/v2/token"
→ HTTP 403: "Resource not accessible by personal access token"
This is the exact endpoint the api-proxy calls. It returns 403 on data residency instances for both fine-grained PATs (with Copilot Requests permission) and GitHub App tokens (ghs_...).
Firewall logs confirm minimal traffic
▼ 2 requests | 2 allowed | 0 blocked | 1 unique domain
| api.contoso-aw.ghe.com | 2 | 0 |
Only 2 requests made before failure — the token exchange attempt and the model list.
Root Cause Analysis
The Copilot CLI has two different authentication paths:
-
Direct (works): When running natively, the CLI uses its own internal auth mechanism (likely device-flow or a different token endpoint) that works on data residency instances. Requires
GH_HOSTto be set. -
Via api-proxy (fails): The AWF api-proxy intercepts Copilot requests and performs its own token exchange at
/copilot_internal/v2/token. This endpoint returns 403 on data residency instances, even with correctly scoped PATs.
The api-proxy was designed for api.github.com where /copilot_internal/v2/token works with PATs. On data residency instances (api.<slug>.ghe.com), this endpoint either doesn't exist or doesn't accept PAT-based authentication.
What needs to change
The api-proxy needs to support GHE Cloud data residency token exchange. Options:
- Use the same auth mechanism as the Copilot CLI — whatever internal auth the CLI uses that works on data residency, the api-proxy should use the same approach
- Pass-through mode — allow the Copilot CLI to handle its own auth directly when
--copilot-api-targetpoints to a non-github.com host, instead of the proxy doing token exchange - Support the data residency token endpoint — if data residency has a different token exchange endpoint or requires a different auth flow, the proxy should detect and use it
Related issues
- gh-aw-firewall#1300 — API proxy routes Copilot requests to GHES API instead of Copilot API (broader GHES routing issue)
- gh-aw-firewall#1302 — Auto-inject GH_HOST in agent container (partially addressed in gh-aw v0.59.0)
- gh-aw#20966 — Audit GHES/GHE Cloud support gaps
Workaround
Currently none. The api-proxy is the mandatory path for Copilot requests inside the AWF sandbox. We confirmed the CLI works outside the sandbox but there is no way to bypass the proxy for production workflow runs.
Timeline of debugging (20+ workflow runs)
| Run | Change | Result |
|---|---|---|
| 22224791–22232891 | Various token/license fixes | 403 on token exchange |
| 22234076 | Added GH_HOST to diagnostic step | CLI works directly! (exit 0) |
| 22234276 | Added GH_HOST to Execute step env | CLI still fails inside container (400 from proxy) |
The breakthrough in run 22234076 proved the problem is isolated to the api-proxy, not Copilot configuration.