fix: strip Anthropic-specific fingerprint headers (anthropic-dangerou…#2228
fix: strip Anthropic-specific fingerprint headers (anthropic-dangerou…#2228Sclock wants to merge 1 commit intorouter-for-me:mainfrom
Conversation
…s-direct-browser-access, x-app, claude-code-20250219 beta) when upstream is not api.anthropic.com.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a critical issue where Anthropic-specific HTTP headers were inadvertently being sent to all upstream API providers, leading to request failures for non-Anthropic services. The core change involves implementing conditional logic within the header application process, ensuring that these specialized headers are now correctly restricted to only Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request effectively addresses the critical issue of Anthropic-specific fingerprint headers being unconditionally forwarded to third-party upstreams. The solution correctly gates these headers based on the isAnthropicBase flag, preventing 400 Improperly formed request errors or hangs with non-Anthropic providers. The addition of the removeBetaFeature helper function is a clean way to manage the Anthropic-Beta header. The new test cases thoroughly validate the fix for both Anthropic and non-Anthropic upstreams, ensuring no regressions. The changes are well-implemented and directly resolve the problem described.
There was a problem hiding this comment.
💡 Codex Review
CLIProxyAPI/internal/runtime/executor/claude_executor.go
Lines 871 to 875 in 5e9b956
applyClaudeHeaders() removes claude-code-20250219 from the default/header-derived beta list, but this merge loop adds it back for any request whose JSON body contains "betas": ["claude-code-20250219"] (see extractAndRemoveBetas() in the same file). For non-api.anthropic.com base_urls, that means the gateway still forwards the incompatible beta and third-party relays can hit the same 400/hang this patch is trying to eliminate. The new tests only cover extraBetas == nil, so this path is still untested.
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
xkonjin left a comment
There was a problem hiding this comment.
Code Review
Overall: Clean, well-scoped fix for a real compatibility issue with third-party upstreams. The approach of conditionally stripping Anthropic-specific headers based on isAnthropicBase is the right pattern.
Observations
removeBetaFeature reuses the input slice backing array (line filtered := parts[:0]). This is fine here since parts is local and discarded after the join, but worth noting: if the input header string were reused elsewhere the shared backing could cause subtle bugs. Not an issue in this call site, just a readability note.
Test coverage is solid. Both the positive case (Anthropic upstream keeps headers) and negative case (non-Anthropic strips them) are covered. The test correctly checks all three header categories: Anthropic-Dangerous-Direct-Browser-Access, X-App, and the claude-code-20250219 beta.
Minor: X-Stainless-* headers are still forwarded to non-Anthropic upstreams. These are also Anthropic/Stainless SDK fingerprint headers. If the goal is to avoid confusing third-party providers, it might be worth gating X-Stainless-Retry-Count, X-Stainless-Runtime-Version, etc. behind isAnthropicBase as well. Third-party providers likely ignore them, but it would be consistent with the intent of the PR.
No bugs or security issues found. LGTM with the minor consideration above.
luispater left a comment
There was a problem hiding this comment.
Summary:
This PR is directionally correct and fixes the unconditional forwarding of Anthropic-Dangerous-Direct-Browser-Access and X-App for non-Anthropic upstreams. However, one blocking gap remains in beta handling.
Key findings:
- Blocking:
claude-code-20250219may still be forwarded to non-Anthropic upstreams if provided via request-bodybetas(extraBetas). The current removal runs before mergingextraBetas, so the later merge can re-introduce the same beta without checkingisAnthropicBase. - Non-blocking: Please add a test for the
extraBetaspath on non-Anthropic upstreams to lock this behavior.
Suggested fix:
- Either filter
extraBetasfor non-Anthropic upstreams before merge, or run a final normalization pass after all beta sources are merged (header/default/body/flags), then setAnthropic-Beta.
Test plan:
- Add/extend unit test:
- non-Anthropic base URL +
extraBetascontainingclaude-code-20250219=> finalAnthropic-Betamust not contain it.
- non-Anthropic base URL +
- Keep existing Anthropic-upstream test to ensure no regression for
api.anthropic.com.
Problem Description
The CLIProxyAPI gateway unconditionally forwards Anthropic-specific fingerprint headers to all upstream providers, including third-party ones like
api.xheai.cc. This causes those upstreams to hang or return400 Improperly formed request, while the same request body sent directly to the upstream (without these headers) succeeds with200 OK.Failing request to gateway (
POST /v1/messages?beta=true, elapsed 1891ms → 400):Gateway response:
{ "error": { "message": "Upstream bad request: Improperly formed request.", "type": "invalid_request_error" } }Direct upstream request (same body, succeeded with 200):
Any one of the following headers is sufficient to trigger the issue:
anthropic-betaclaude-code-20250219+ modelclaude-opus-4-6anthropic-dangerous-direct-browser-accesstruex-appcliRoot Cause Analysis (RCA)
Location:
internal/runtime/executor/claude_executor.go, functionapplyClaudeHeaders()The function already computes
isAnthropicBaseto distinguishapi.anthropic.comfrom other upstreams, but only uses it for auth header selection. The three Anthropic-specific fingerprint headers are set unconditionally:The existing configuration system (
ClaudeHeaderDefaults, per-keyheadersmap) cannot work around this: custom headers can only add or overwrite values, not conditionally suppress headers that are hardcoded earlier in the same function.Fix
Reuse the existing
isAnthropicBaseflag to gate the three problematic headers.New helper added in the same file:
The fix applies to all three call sites of
applyClaudeHeaders—Execute(),ExecuteStream(), andCountTokens()— in a single change.Alternative considered: filtering at the handler or middleware layer — rejected because it would require duplicating logic across multiple paths, while
applyClaudeHeadersis the single shared call site.Test Verification
New tests in
internal/runtime/executor/claude_executor_test.go:Before fix (RED):
After fix (GREEN):
Full test suite:
Impact Assessment
api.anthropic.combase_url. Credentials pointing atapi.anthropic.comare unaffected.Checklist