fix(ai): use pass-through endpoint for Claude Max OAuth forwarding#965
fix(ai): use pass-through endpoint for Claude Max OAuth forwarding#965jlengelbrecht merged 1 commit intomainfrom
Conversation
STORY-063: Workaround for LiteLLM bug #19618 where clean_headers() strips Authorization header before forwarding to Anthropic. Pass-through endpoint with forward_headers: true preserves all client headers including OAuth token for Claude Max subscription. Changes: - Add /anthropic pass-through endpoint in LiteLLM ConfigMap - Configure guardrails (lakera-guard, openai-mod) on pass-through - Update Moltbot ANTHROPIC_BASE_URL to use pass-through path - Remove ANTHROPIC_MODEL (not needed with pass-through) Reference: https://docs.litellm.ai/docs/pass_through/anthropic_completion
ℹ️ SOPS Encryption CheckNo SOPS files detected in this pull request.
No encryption validation required for this PR. |
✅ Gitleaks Secret Scan PassedNo secrets detected in this pull request.
|
WalkthroughThe changes configure Anthropic API pass-through forwarding in LiteLLM with per-message content guardrails, while updating MoltBot's Anthropic client configuration to route through the new LiteLLM Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Key attention areas:
Suggested labels
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
--- kubernetes/apps/ai/moltbot/app Kustomization: ai/moltbot HelmRelease: ai/moltbot
+++ kubernetes/apps/ai/moltbot/app Kustomization: ai/moltbot HelmRelease: ai/moltbot
@@ -51,20 +51,18 @@
fs.writeFileSync(f, JSON.stringify(c, null, 2));
"
exec node dist/entry.js gateway \
--port 18789 --bind lan --verbose
env:
ANTHROPIC_BASE_URL:
- value: http://litellm.ai.svc.cluster.local:4000
+ value: http://litellm.ai.svc.cluster.local:4000/anthropic
ANTHROPIC_CUSTOM_HEADERS:
valueFrom:
secretKeyRef:
key: ANTHROPIC_CUSTOM_HEADERS
name: moltbot-secrets
- ANTHROPIC_MODEL:
- value: claude-default
ANTHROPIC_OAUTH_TOKEN:
valueFrom:
secretKeyRef:
key: ANTHROPIC_OAUTH_TOKEN
name: moltbot-secrets
CLAWDBOT_GATEWAY_TOKEN:
--- kubernetes/apps/ai/litellm/app Kustomization: ai/litellm ConfigMap: ai/litellm-config
+++ kubernetes/apps/ai/litellm/app Kustomization: ai/litellm ConfigMap: ai/litellm-config
@@ -219,12 +219,30 @@
# STORY-150: Request timeout must accommodate longest cold start (wan-video: 420s)
# Per-model timeouts take precedence, but this is the fallback default
request_timeout: 420
# STORY-059: Allow setting api_base for search tools via admin API
# Required to configure self-hosted SearXNG endpoint
allow_client_side_credentials: true
+
+ # =====================================================
+ # STORY-063: Anthropic Pass-Through for Claude Max OAuth
+ # Workaround for LiteLLM bug (Issue #19618) where Authorization
+ # header is stripped before forwarding to Anthropic.
+ # Pass-through with forward_headers: true preserves OAuth token.
+ # Reference: https://docs.litellm.ai/docs/pass_through/anthropic_completion
+ # =====================================================
+ pass_through_endpoints:
+ - path: "/anthropic"
+ target: "https://api.anthropic.com"
+ forward_headers: true
+ auth: true
+ guardrails:
+ lakera-guard:
+ request_fields: ["messages[*].content"]
+ openai-mod:
+ request_fields: ["messages[*].content"]
litellm_settings:
# Drop unsupported params instead of erroring
drop_params: true
# Enable logging for audit
set_verbose: false |
--- HelmRelease: ai/moltbot Deployment: ai/moltbot
+++ HelmRelease: ai/moltbot Deployment: ai/moltbot
@@ -103,20 +103,18 @@
fs.writeFileSync(f, JSON.stringify(c, null, 2));
"
exec node dist/entry.js gateway \
--port 18789 --bind lan --verbose
env:
- name: ANTHROPIC_BASE_URL
- value: http://litellm.ai.svc.cluster.local:4000
+ value: http://litellm.ai.svc.cluster.local:4000/anthropic
- name: ANTHROPIC_CUSTOM_HEADERS
valueFrom:
secretKeyRef:
key: ANTHROPIC_CUSTOM_HEADERS
name: moltbot-secrets
- - name: ANTHROPIC_MODEL
- value: claude-default
- name: ANTHROPIC_OAUTH_TOKEN
valueFrom:
secretKeyRef:
key: ANTHROPIC_OAUTH_TOKEN
name: moltbot-secrets
- name: CLAWDBOT_GATEWAY_TOKEN |
There was a problem hiding this comment.
Pull request overview
Routes Anthropic (Claude Max OAuth) traffic through LiteLLM using a pass-through endpoint to work around a LiteLLM bug that strips the Authorization header during normal forwarding.
Changes:
- Adds a LiteLLM
/anthropicpass-through endpoint targetinghttps://api.anthropic.comwith header forwarding enabled. - Updates Moltbot to use the new
/anthropicbase URL path (and removes the explicitANTHROPIC_MODELenv var).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| kubernetes/apps/ai/moltbot/app/helmrelease.yaml | Points Moltbot’s Anthropic base URL at LiteLLM’s new /anthropic pass-through endpoint. |
| kubernetes/apps/ai/litellm/app/configmap.yaml | Adds the pass-through endpoint configuration intended to preserve Anthropic OAuth headers and keep guardrails enabled. |
| # Pass-through with forward_headers: true preserves OAuth token. | ||
| # Reference: https://docs.litellm.ai/docs/pass_through/anthropic_completion | ||
| # ===================================================== | ||
| pass_through_endpoints: | ||
| - path: "/anthropic" | ||
| target: "https://api.anthropic.com" | ||
| forward_headers: true |
There was a problem hiding this comment.
forward_headers: true will forward all incoming headers to https://api.anthropic.com, which can leak LiteLLM authentication material (e.g., Authorization: Bearer <master/virtual key> for clients that use bearer auth, and/or x-litellm-api-key) to the upstream provider. Since litellm ingress allows traffic from any pod in the ai namespace (and the internal gateway), this is a real credential-exfil path. Prefer forwarding only the minimal required header(s) for Claude Max OAuth (typically Authorization) and explicitly ensure LiteLLM auth headers are not forwarded upstream (e.g., via an allowlist/denylist mechanism or a dedicated auth header for LiteLLM separate from Authorization).
| # Pass-through with forward_headers: true preserves OAuth token. | |
| # Reference: https://docs.litellm.ai/docs/pass_through/anthropic_completion | |
| # ===================================================== | |
| pass_through_endpoints: | |
| - path: "/anthropic" | |
| target: "https://api.anthropic.com" | |
| forward_headers: true | |
| # Pass-through with a restricted forward_headers allowlist preserves | |
| # the OAuth token without leaking LiteLLM-specific auth headers. | |
| # Reference: https://docs.litellm.ai/docs/pass_through/anthropic_completion | |
| # ===================================================== | |
| pass_through_endpoints: | |
| - path: "/anthropic" | |
| target: "https://api.anthropic.com" | |
| forward_headers: | |
| - "authorization" | |
| - "anthropic-version" | |
| - "anthropic-beta" |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@kubernetes/apps/ai/litellm/app/configmap.yaml`:
- Around line 238-241: The pass-through route for path "/anthropic" currently
uses forward_headers: true which leaks all client headers; remove
forward_headers: true from the /anthropic route in configmap.yaml and either add
a explicit headers: list containing only required headers for Anthropic, or
implement an upstream proxy (NGINX/Envoy) to strip sensitive headers before
requests reach the /anthropic target, or replace the pass-through with a custom
adapter that constructs outgoing requests with only safe headers; update the
configuration for the "/anthropic" route (path "/anthropic", target
"https://api.anthropic.com") accordingly.
| - path: "/anthropic" | ||
| target: "https://api.anthropic.com" | ||
| forward_headers: true | ||
| auth: true |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
LiteLLM forward_headers allowlist header filtering pass-through proxy
💡 Result:
In LiteLLM pass-through endpoints, header forwarding is currently all-or-nothing:
forward_headers: truewill forward all incoming request headers to the target endpoint. (docs.litellm.ai)- There is no documented “allowlist” / per-header filter option for pass-through routes (the pass-through config spec only exposes
headers:(static headers) andforward_headers:(boolean)). (docs.litellm.ai)
Example (forwards everything):
general_settings:
pass_through_endpoints:
- path: "/v1/rerank"
target: "https://api.cohere.com/v1/rerank"
headers:
Authorization: "bearer os.environ/COHERE_API_KEY"
content-type: application/json
accept: application/json
forward_headers: trueIf you need an allowlist (only some headers)
You’ll need to do it outside of pass-through, e.g.:
- Put an upstream proxy (NGINX/Envoy/API Gateway) in front of LiteLLM to strip/allow only specific headers before they reach LiteLLM, or
- Write a custom adapter/callback that explicitly constructs the outbound request/headers, instead of using a pure pass-through route. (docs.litellm.ai)
Related (non pass-through) header forwarding controls
For normal model calls (not pass-through), LiteLLM provides forward_client_headers_to_llm_api, which enables forwarding for specific model groups, but it still isn’t a per-header allowlist; it forwards certain categories (notably x-* headers, with some exclusions) when enabled. (docs.litellm.ai)
Also note there’s been historical confusion/bugs around pass-through header behavior (see GitHub issue). (github.com)
Citations:
- 1: https://docs.litellm.ai/docs/proxy/pass_through
- 2: https://docs.litellm.ai/docs/proxy/pass_through
- 3: https://docs.litellm.ai/docs/proxy/pass_through
- 4: https://docs.litellm.ai/docs/proxy/pass_through
- 5: https://docs.litellm.ai/docs/proxy/forward_client_headers
- 6: Pass through endpoints do not have a way to pass through original request headers BerriAI/litellm#5060
🌐 Web query:
LiteLLM pass-through proxy configuration header forwarding documentation
💡 Result:
LiteLLM “pass-through proxy” header forwarding is documented under Pass Through Endpoints:
-
Config key:
general_settings.pass_through_endpoints[].forward_headers: true
This enables forwarding the original incoming request headers to the upstream “target” endpoint (in addition to any staticheaders:you define). Example in docs showsheaders:plusforward_headers: true. [1] -
Where it’s documented: “Create Pass Through Endpoints” → Config.yaml Setup / Configuration Reference (includes
headersandforward_headers). [1]
Related (non-pass-through) header forwarding docs (for forwarding client headers to LLM provider APIs, not arbitrary pass-through targets):
general_settings.forward_client_headers_to_llm_api: true(global) or enable per model group vialitellm_settings.model_group_settings.forward_client_headers_to_llm_api. [3]- Overview of supported/special request headers is listed under “Request Headers”. [2]
Sources:
[1] LiteLLM Docs — Create Pass Through Endpoints (pass-through + forward_headers) (docs.litellm.ai)
[2] LiteLLM Docs — Request Headers (docs.litellm.ai)
[3] LiteLLM Docs — Forward Client Headers to LLM API (docs.litellm.ai)
Citations:
- 1: https://docs.litellm.ai/docs/proxy/pass_through?utm_source=openai
- 2: https://docs.litellm.ai/docs/proxy/request_headers?utm_source=openai
- 3: https://docs.litellm.ai/docs/proxy/forward_client_headers?utm_source=openai
🌐 Web query:
LiteLLM "forward_headers" allowed_headers whitelist configuration
💡 Result:
LiteLLM has two different “forward headers” features, and neither currently supports an allowed_headers (whitelist) config knob:
1) Proxy → LLM provider header forwarding (model-group controlled)
This is configured via forward_client_headers_to_llm_api (globally or per model group). When enabled, LiteLLM forwards only specific categories (effectively a built-in allowlist), e.g.:
- Custom
x-...headers (with exceptions likex-stainless-*) - Some provider-specific headers (e.g., Anthropic beta headers; OpenAI org header when separately enabled)
There is no documentedallowed_headerswhitelist you can set—control is via enabling/disabling forwarding per model group. [1]
2) Pass-through endpoints header forwarding
For pass_through_endpoints, the per-route flag is:
general_settings:
pass_through_endpoints:
- path: "/v1/..."
target: "https://..."
forward_headers: trueforward_headers: true forwards all incoming request headers to the target endpoint; docs do not mention any allowed_headers filtering/whitelist option. [2]
If you need a whitelist today
- For pass-through endpoints, you generally have to not use
forward_headers: trueand instead explicitly set/override the needed headers underheaders:(but that won’t dynamically “pass through” arbitrary client headers). Lack of fine-grained “forward only these headers” control has been raised as a feature request/limitation. [3]
Sources: Forward client headers docs [1], pass-through endpoint docs [2], related GitHub issue discussing header pass-through control [3].
Remove forward_headers: true or implement header filtering to prevent credential leakage.
forward_headers: true forwards all incoming client headers to Anthropic, including internal LiteLLM auth credentials and cookies. LiteLLM's pass-through endpoint configuration does not support an allowlist—you must either:
- Remove
forward_headers: trueand explicitly define only required headers underheaders: - Deploy an upstream proxy (NGINX/Envoy) in front of LiteLLM to strip sensitive headers before reaching the pass-through endpoint
- Replace the pass-through route with a custom adapter that constructs requests with only safe headers
Without one of these mitigations, all client headers are forwarded to the external Anthropic API.
🤖 Prompt for AI Agents
In `@kubernetes/apps/ai/litellm/app/configmap.yaml` around lines 238 - 241, The
pass-through route for path "/anthropic" currently uses forward_headers: true
which leaks all client headers; remove forward_headers: true from the /anthropic
route in configmap.yaml and either add a explicit headers: list containing only
required headers for Anthropic, or implement an upstream proxy (NGINX/Envoy) to
strip sensitive headers before requests reach the /anthropic target, or replace
the pass-through with a custom adapter that constructs outgoing requests with
only safe headers; update the configuration for the "/anthropic" route (path
"/anthropic", target "https://api.anthropic.com") accordingly.
Summary
Workaround for LiteLLM bug #19618 where
clean_headers()strips the Authorization header before forwarding to Anthropic, breaking Claude Max OAuth authentication.Relates to: STORY-063
The Problem
LiteLLM's header processing strips the Authorization header containing the OAuth token before it can be forwarded to Anthropic. This prevents Claude Max subscription authentication from working through LiteLLM.
Fix PRs exist (#19802, #19912) but are not yet merged.
Solution
Use LiteLLM's pass-through endpoint feature with
forward_headers: true, which bypasses the header stripping logic and forwards all client headers (including Authorization) directly to Anthropic.Changes
LiteLLM ConfigMap:
/anthropicpass-through endpoint targetinghttps://api.anthropic.comforward_headers: trueto preserve OAuth tokenMoltbot HelmRelease:
ANTHROPIC_BASE_URLto use pass-through path (/anthropic)ANTHROPIC_MODEL(model specified in request body with pass-through)Security
auth: true)Testing
References
Pull Request Summary
Services and Namespaces Affected
Breaking Changes
http://litellm.ai.svc.cluster.local:4000tohttp://litellm.ai.svc.cluster.local:4000/anthropic- requires coordinated deployment of both LiteLLM and Moltbot to maintain service continuitySecurity Implications
forward_headers: truepreserves the Authorization header for Claude Max OAuth authentication, forwarding the token only to Anthropic API (https://api.anthropic.com)/anthropicendpoint viarequest_fields: ["messages[*].content"]auth: truesetting on the pass-through endpoint ensures all requests still require LiteLLM master key authentication before forwarding to Anthropicclean_headers()to strip Authorization headers before forwarding requestsFlux Dependency Impacts
Resource Changes
/anthropicpass-through endpoint with guardrail configuration inpass_through_endpoints)Deployment Checklist
/anthropicrequests