-
Notifications
You must be signed in to change notification settings - Fork 18
api-proxy: Anthropic API calls rejected despite correct routing (auth chain failure) #1527
Description
Problem
After the chroot key helper fix (PR #1508), the script copy and config path updates work correctly, and the firewall allows traffic through to api.anthropic.com. However, all Anthropic API calls fail with error: "unknown", error_status: null, and zero tokens consumed — indicating the requests reach Anthropic but are rejected.
Observed behavior (from gh-aw#23614 comment)
[entrypoint] ✓ Updated apiKeyHelper path in /host/home/runner/.claude.json
[entrypoint] ✓ Updated apiKeyHelper path in /host/home/runner/.claude/settings.json
[entrypoint] Claude key helper copied to chroot at /tmp/awf-lib/get-claude-key.sh
- ✅ Chroot fix works (paths updated)
- ✅ Squid allows 4 requests to
api.anthropic.com(0 blocked) - ❌ All 10 API retries fail:
error: "unknown",error_status: null - ❌ Zero tokens consumed, zero cost — API never successfully authenticated
The ANTHROPIC_API_KEY works fine outside gh-aw (validated by the activation step).
Environment
- AWF: v0.25.4
- gh-aw: v0.64.5
- Claude Code CLI: 2.1.88
- Failed run: https://github.com/usepepper/salsa/actions/runs/23814978435
Authentication Chain Analysis
The expected chain:
Claude Code → apiKeyHelper (get-claude-key.sh)
→ returns "sk-ant-placeholder-key-for-credential-isolation"
→ sends x-api-key: <placeholder> to ANTHROPIC_BASE_URL (http://172.30.0.30:10001)
→ api-proxy strips x-api-key, injects real ANTHROPIC_API_KEY
→ forwards through Squid to api.anthropic.com
→ Anthropic authenticates with real key
The chain breaks somewhere between the api-proxy injecting the key and Anthropic accepting the request.
Hypotheses
H1: Claude Code 2.1.88 auth mechanism mismatch
Claude Code may use a different auth flow than the standard Anthropic SDK:
- Might send
Authorization: Bearerinstead of or in addition tox-api-key - Might use a different API endpoint path (e.g.,
/v1/completevs/v1/messages) - Might require an
anthropic-versionheader value newer than the proxy's default2023-06-01
The api-proxy strips authorization and x-api-key headers and only injects x-api-key. If Claude Code requires a header the proxy doesn't inject, auth would fail.
H2: ANTHROPIC_AUTH_TOKEN interference
The agent has TWO different placeholder values:
ANTHROPIC_AUTH_TOKEN=placeholder-token-for-credential-isolation(env var,docker-manager.ts:1450)apiKeyHelperreturnssk-ant-placeholder-key-for-credential-isolation(script output)
Claude Code might prefer ANTHROPIC_AUTH_TOKEN over apiKeyHelper for certain operations, sending it as a different header that the proxy doesn't handle. Or the two conflicting values might cause confusion in Claude Code's auth logic.
H3: SSE streaming response not proxied correctly
The error_status: null (not 401/403) suggests Claude Code can't parse the response rather than receiving a clear auth error. The api-proxy uses proxyRequest() which pipes the upstream response back — if SSE chunked encoding is mangled, Claude Code would see "unknown" errors.
H4: Squid CONNECT tunnel issue
The 4 "allowed" Squid requests might be CONNECT tunnel establishments (HTTP 200), not the actual API calls. The real API responses within the tunnel might be failing. Squid logs showing TCP_TUNNEL:HIER_DIRECT with status 200 only means the tunnel was established, not that the API call succeeded.
Suggested Investigation
- Enable api-proxy debug logging and check if requests are being received and forwarded with the correct
x-api-keyheader - Compare headers sent by Claude Code 2.1.88 vs what the proxy expects — check if Claude Code sends auth in a header the proxy doesn't handle
- Check the Anthropic response status in the api-proxy logs (before it's sent back to the agent)
- Test with
curlthrough the same proxy chain to isolate whether it's a Claude Code-specific issue:curl -v http://172.30.0.30:10001/v1/messages \ -H "content-type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{"model":"claude-sonnet-4-20250514","max_tokens":10,"messages":[{"role":"user","content":"hi"}]}'
- Try removing
ANTHROPIC_AUTH_TOKENfrom the agent environment to see if it interferes withapiKeyHelper
References
- Upstream: engine: claude — get-claude-key.sh missing in chroot (AWF v0.25.4), apiKeyHelper exit 127 gh-aw#23614
- Chroot fix: fix: copy get-claude-key.sh to chroot-accessible path #1508
- Config path fix: fix: write apiKeyHelper to ~/.claude/settings.json for Claude Code v2.1.81+ #1414
- Api-proxy Anthropic handler:
containers/api-proxy/server.js:718-749 - Key helper:
containers/agent/get-claude-key.sh - Agent env setup:
src/docker-manager.ts:1438-1457 - Api-proxy env setup:
src/docker-manager.ts:1358-1370