fix: api-proxy auth chain — trim keys, align placeholder format, add diagnostics#1528
fix: api-proxy auth chain — trim keys, align placeholder format, add diagnostics#1528
Conversation
…diagnostics Three fixes for the Anthropic API proxy auth chain failure (#1527): 1. Trim API keys read from env vars in api-proxy (server.js) CI secrets and docker-compose YAML may include trailing whitespace or newlines. Untrimmed keys produce malformed HTTP headers (the newline terminates the header prematurely), causing silent auth failures with error_status: null. 2. Align ANTHROPIC_AUTH_TOKEN placeholder with sk-ant- key format Claude Code validates key format before making API calls. The old placeholder 'placeholder-token-for-credential-isolation' lacks the sk-ant- prefix and may fail format validation. Now uses the same value as apiKeyHelper: 'sk-ant-placeholder-key-for-credential-isolation'. 3. Add auth header injection + upstream error logging in api-proxy - 'auth_inject' debug log confirms key injection (length, preview) - 'upstream_auth_error' warning on 401/403 from upstream API Closes #1527 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
✅ Coverage Check PassedOverall Coverage
📁 Per-file Coverage Changes (1 files)
Coverage comparison generated by |
There was a problem hiding this comment.
Pull request overview
Fixes Anthropic authentication failures in the api-proxy credential-isolation chain by preventing malformed auth headers, aligning placeholder token format with Claude Code validation expectations, and adding targeted diagnostics for auth injection and upstream auth errors.
Changes:
- Trim whitespace/newlines from API key env vars in
api-proxybefore injecting headers. - Update
ANTHROPIC_AUTH_TOKENplaceholder to ansk-ant--prefixed value and adjust related tests. - Add structured logs for auth header injection and explicit warnings on upstream 401/403 responses.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
containers/api-proxy/server.js |
Trim env-provided credentials; add auth injection debug logging and upstream 401/403 diagnostics. |
src/docker-manager.ts |
Change Claude Code placeholder token to an sk-ant--prefixed value for format validation compatibility. |
src/docker-manager.test.ts |
Update unit test expectations for the new Anthropic placeholder token value. |
tests/integration/api-proxy.test.ts |
Update integration test expectation for the new Anthropic placeholder token value. |
Comments suppressed due to low confidence (2)
containers/api-proxy/server.js:342
- Logging
key_previewstill reveals parts of the injected credential (first 8 + last 4 chars). Even partial token logging can be considered sensitive and can leak identifying material. Prefer logging only non-sensitive metadata (e.g., key length, header type) or a one-way hash/fingerprint.
const keyPreview = injectedKey.length > 8
? `${injectedKey.substring(0, 8)}...${injectedKey.substring(injectedKey.length - 4)}`
: '(short)';
containers/api-proxy/server.js:349
logRequestis documented as taking level "info" | "warn" | "error" (see containers/api-proxy/logging.js), but this introduces a new "debug" level. Either update the logging contract/tests to explicitly support "debug", or log this event at an existing level to avoid surprising downstream log consumers.
logRequest('debug', 'auth_inject', {
request_id: requestId,
provider,
key_length: injectedKey.length,
key_preview: keyPreview,
has_anthropic_version: !!headers['anthropic-version'],
});
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Real authentication happens via ANTHROPIC_BASE_URL pointing to api-proxy | ||
| environment.ANTHROPIC_AUTH_TOKEN = 'placeholder-token-for-credential-isolation'; | ||
| // Use sk-ant- prefix so Claude Code's key-format validation passes | ||
| environment.ANTHROPIC_AUTH_TOKEN = 'sk-ant-placeholder-key-for-credential-isolation'; |
There was a problem hiding this comment.
Changing ANTHROPIC_AUTH_TOKEN placeholder here will cause the agent entrypoint pre-flight script (containers/agent/api-proxy-health-check.sh) to exit 1 because it still hard-codes the previous value ('placeholder-token-for-credential-isolation'). Update the health check to accept the new placeholder (or relax the check) so api-proxy-enabled runs don’t fail before the user command executes.
| environment.ANTHROPIC_AUTH_TOKEN = 'sk-ant-placeholder-key-for-credential-isolation'; | |
| environment.ANTHROPIC_AUTH_TOKEN = 'sk-ant-placeholder-token-for-credential-isolation'; |
| Object.assign(headers, injectHeaders); | ||
|
|
||
| // Log auth header injection for debugging credential-isolation issues | ||
| const injectedKey = injectHeaders['x-api-key'] || injectHeaders['authorization']; |
There was a problem hiding this comment.
injectHeaders uses 'Authorization' (capital A) for OpenAI/Copilot, but this diagnostic checks only injectHeaders['authorization'] (lowercase). As a result, auth_inject logs won’t trigger for those providers. Consider normalizing header keys (e.g., lowercasing injectHeaders keys) or checking both cases so the diagnostic works consistently.
This issue also appears in the following locations of the same file:
- line 340
- line 343
| const injectedKey = injectHeaders['x-api-key'] || injectHeaders['authorization']; | |
| const injectedKey = injectHeaders['x-api-key'] | |
| || injectHeaders['authorization'] | |
| || injectHeaders['Authorization']; |
|
🤖 Smoke test results for
Overall: PASS
|
Chroot Version Comparison Results
Overall: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
The api-proxy-health-check.sh validates that ANTHROPIC_AUTH_TOKEN contains a placeholder value. Update the expected value to match the new sk-ant- prefixed placeholder set in docker-manager.ts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Smoke Test Results — Copilot Engine
Overall: PASS PR author:
|
|
Smoke Test Results ✅ GitHub MCP: "fix: copy get-claude-key.sh to chroot-accessible path", "feat: add volume mount for ~/.copilot/session-state to persist events.jsonl" Overall: PASS
|
Chroot Version Comparison Results
Result: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.
|
🏗️ Build Test Suite Results
Overall: 8/8 ecosystems passed — ✅ PASS
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Smoke test results (workflow run 23824467737)
|
Summary
Fixes #1527 — Anthropic API calls rejected despite correct routing through the api-proxy auth chain.
Changes
1. Trim API keys in api-proxy (
containers/api-proxy/server.js)CI secrets and docker-compose YAML may include trailing whitespace or newlines. When the api-proxy reads
ANTHROPIC_API_KEYfrom its environment and injects it into thex-api-keyheader without trimming, a trailing newline corrupts the HTTP header (the newline terminates it prematurely). This produces silent auth failures where the upstream returns an error that Claude Code reports aserror: "unknown", error_status: null.2. Align
ANTHROPIC_AUTH_TOKENplaceholder withsk-ant-key format (src/docker-manager.ts)Claude Code validates API key format before making calls. The old placeholder
placeholder-token-for-credential-isolationlacks thesk-ant-prefix that Claude Code expects. Now uses the same value asapiKeyHelperoutput:sk-ant-placeholder-key-for-credential-isolation.This also eliminates the inconsistency where the agent had two different placeholder values:
ANTHROPIC_AUTH_TOKEN=placeholder-token-for-credential-isolation(env var) ← fixedapiKeyHelper→sk-ant-placeholder-key-for-credential-isolation(script output)3. Add auth header injection + upstream error logging (
containers/api-proxy/server.js)auth_injectdebug log: Confirms the real API key is being injected (shows key length and redacted preview, not the actual key)upstream_auth_errorwarning: Prominently logs 401/403 responses from upstream APIs with a diagnostic messageThese logs make it possible to diagnose credential-isolation failures without access to the actual API keys.
Testing
docker-manager.test.ts, 3 pre-existing sudo failures unrelated)containers/api-proxy/)References