Skip to content

[Feature] UI - Settings: Claude Code BYOK support#25998

Merged
yuneng-berri merged 9 commits intolitellm_internal_stagingfrom
litellm_/wonderful-bouman
Apr 18, 2026
Merged

[Feature] UI - Settings: Claude Code BYOK support#25998
yuneng-berri merged 9 commits intolitellm_internal_stagingfrom
litellm_/wonderful-bouman

Conversation

@yuneng-berri
Copy link
Copy Markdown
Collaborator

Relevant issues

(none)

Summary

Exposes Claude Code BYOK (bring-your-own-key) configuration in the admin UI so admins no longer need to edit config.yaml to enable it.

Problem

The Claude Code BYOK tutorial (docs/my-website/docs/tutorials/claude_code_byok.md) has two proxy-side config requirements that were previously only settable via YAML:

  1. Add an Anthropic model with no api_key (so the client's forwarded key is used).
  2. Set forward_llm_provider_auth_headers: true.

Neither was achievable from the UI. The add-model form blocked empty api_key (Anthropic was marked required: true), and the BYOK flag was only readable from config.yaml. Admins without env-var or file access had no way to complete the setup.

What this does

  • Adds forward_llm_provider_auth_headers to UISettings (Pydantic model + allowlist + runtime sync list) and a toggle row on the UI Settings page, following the existing forward_client_headers_to_llm_api pattern (DB-override-config via litellm_uisettings).
  • Relaxes Anthropic's api_key to required: false in provider_create_fields.json with a BYOK-explaining tooltip.
  • Adds an optional api_base field to the Anthropic entry (matches AI21 / ANTHROPIC_TEXT), with a tooltip that explicitly warns against setting it to the proxy URL.
  • Updates the existing "Forward client headers to LLM API" and the new "Forward LLM provider auth headers" toggle descriptions to clarify when to enable each (Max subscription vs BYOK) and that they are independent.
  • Documents the UI-only configuration path in the BYOK tutorial.

Changes

UISettings.tsx + proxy_setting_endpoints.py add the toggle and its wiring. provider_create_fields.json relaxes the Anthropic api_key requirement and adds api_base. Tests cover the settings persistence + runtime sync, the clean_headers BYOK forwarding path (including the anti-replay guard where x-api-key was used for proxy auth), and the Anthropic provider form shape/ordering.

Testing

New unit tests:

  • test_update_ui_settings_persists_forward_llm_provider_auth_headers
  • test_update_ui_settings_syncs_forward_llm_provider_auth_headers_to_general_settings
  • test_clean_headers_preserves_x_api_key_when_byok_enabled
  • test_clean_headers_strips_x_api_key_when_byok_disabled
  • test_clean_headers_strips_x_api_key_when_byok_enabled_but_x_api_key_was_auth_header
  • test_anthropic_provider_fields_support_byok

Full test files pass: test_proxy_setting_endpoints.py, test_public_endpoints.py, test_litellm_pre_call_utils.py. ui/litellm-dashboard builds with npm run build; npx tsc --noEmit clean on the modified file.

Verified end-to-end with a local proxy + Docker Postgres:

  • GET /get/ui_settings schema exposes the toggle
  • PATCH /update/ui_settings persists and round-trips via DB
  • GET /public/providers/fields returns Anthropic with api_key.required=false and api_base present, ordered before api_key
  • Claude Code with /login using an Anthropic API key routes through LiteLLM, forwards the client's key to Anthropic, and logs the call under the virtual key
  • Toggling OFF strips the header and produces a Missing Anthropic API Key error as expected

Type

🆕 New Feature
✅ Test
📖 Documentation

Screenshots

(to be added: the two toggles on Settings → UI Settings, and the Anthropic Add Model form showing the optional API Key and new Upstream API Base fields)

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

…itellm_/wonderful-bouman

# Conflicts:
#	tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py
@yuneng-berri yuneng-berri temporarily deployed to integration-postgres April 18, 2026 04:32 — with GitHub Actions Inactive
@gitguardian
Copy link
Copy Markdown

gitguardian Bot commented Apr 18, 2026

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
29203065 Triggered JSON Web Token e004876 tests/test_litellm/proxy/test_litellm_pre_call_utils.py View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@yuneng-berri yuneng-berri temporarily deployed to integration-postgres April 18, 2026 04:33 — with GitHub Actions Inactive
@yuneng-berri yuneng-berri temporarily deployed to integration-postgres April 18, 2026 04:33 — with GitHub Actions Inactive
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 18, 2026

Greptile Summary

This PR exposes the Claude Code BYOK configuration in the admin UI by adding a forward_llm_provider_auth_headers toggle to the UI Settings page, relaxing the Anthropic api_key field to optional, and adding an api_base field — wired end-to-end with DB persistence, runtime sync into general_settings, and unit tests.

  • P1 security gap in clean_headers: The anti-replay guard that prevents x-api-key from being forwarded when it was used for proxy auth is not applied to api-key (Azure), the Google AI Studio header, or the Azure APIM header — all of which are also accepted by user_api_key_auth. Additionally, the authenticated_with_header detection at lines 950–959 defaults to \"x-api-key\" for any request that doesn't use x-litellm-api-key or authorization, so the guard would still not fire correctly even if added without fixing detection first.

Confidence Score: 4/5

Safe to merge for Anthropic BYOK (x-api-key path is correct), but anti-replay gap for other provider auth headers should be fixed before extending BYOK to Azure/Google providers.

One P1 security finding in the auth layer: the incomplete authenticated_with_header guard leaves api-key and other special headers unprotected when BYOK is enabled. Primary Anthropic use case is correctly implemented; all other changes are clean.

litellm/proxy/litellm_pre_call_utils.py — both the clean_headers third elif branch (lines 326–336) and the authenticated_with_header detection block (lines 950–959) need the anti-replay guard extended to all provider auth headers.

Security Review

  • Credential forwarding without auth guard (litellm/proxy/litellm_pre_call_utils.py, clean_headers lines 326–336): When BYOK is enabled, api-key (Azure), the Google AI Studio header, and the Azure APIM subscription header are forwarded to upstream without checking authenticated_with_header. The x-api-key path has the anti-replay guard; these other provider auth headers do not.
  • Incomplete auth-header detection (lines 950–959): The authenticated_with_header fallback hard-codes \"x-api-key\" for any request that doesn't include x-litellm-api-key or authorization, so the guard would not fire correctly for api-key even if added.

Important Files Changed

Filename Overview
litellm/proxy/litellm_pre_call_utils.py New clean_headers parameters add BYOK forwarding; x-api-key anti-replay guard is correct, but other provider auth headers lack the same guard and authenticated_with_header detection has an incorrect hardcoded fallback.
litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py Adds forward_llm_provider_auth_headers to UISettings model, ALLOWED_UI_SETTINGS_FIELDS, and _RUNTIME_GENERAL_SETTINGS_FLAGS; follows existing pattern exactly.
litellm/proxy/public_endpoints/provider_create_fields.json Makes Anthropic api_key optional with BYOK tooltip, adds api_base field before api_key — both intentional for BYOK.
ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx Adds Switch row for forward_llm_provider_auth_headers using antd components, following exact existing pattern.
tests/test_litellm/proxy/test_litellm_pre_call_utils.py Three mock-only unit tests covering BYOK x-api-key forwarding, stripping, and anti-replay guard.
tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py Two mock-based tests verifying forward_llm_provider_auth_headers persistence and general_settings sync.
docs/my-website/docs/tutorials/claude_code_byok.md Docs-only addition of UI configuration path for BYOK.

Comments Outside Diff (1)

  1. litellm/proxy/litellm_pre_call_utils.py, line 326-336 (link)

    P1 security Anti-replay guard incomplete for other provider auth headers

    This elif branch forwards api-key (Azure), the Google AI Studio header, and the Azure APIM header to upstream without checking authenticated_with_header. The guard that protects x-api-key (lines 320–325) is not applied here. All three of these headers are also accepted by user_api_key_auth for proxy authentication — so a client who uses api-key to auth with the proxy while BYOK is enabled will have their LiteLLM virtual key forwarded to the upstream LLM provider.

    There is also a gap at lines 950–959: when neither x-litellm-api-key nor authorization is present, the else branch always writes "x-api-key" as the fallback regardless of which header actually carried the proxy credential. This means the guard would still not fire correctly for api-key even after being added here.

    Two changes are needed:

    1. Add the auth-header guard to this branch (same pattern used for x-api-key):
        if (
            authenticated_with_header is not None
            and header_lower == authenticated_with_header.lower()
        ):
            continue
        clean_headers[header] = value
    1. Detect each provider header explicitly at the call site instead of defaulting to a hardcoded string:
    if "x-litellm-api-key" in request.headers:
        authenticated_with_header = "x-litellm-api-key"
    elif "authorization" in request.headers:
        authenticated_with_header = "authorization"
    elif "api-key" in request.headers:
        authenticated_with_header = "api-key"
    elif "x-api-key" in request.headers:
        authenticated_with_header = "x-api-key"
    else:
        authenticated_with_header = None

    Rule Used: What: Fail any PR which may contains a security in... (source)

Reviews (1): Last reviewed commit: "Merge remote-tracking branch 'origin/lit..." | Re-trigger Greptile

@yuneng-berri yuneng-berri merged commit 18a5fe5 into litellm_internal_staging Apr 18, 2026
93 of 98 checks passed
@yuneng-berri yuneng-berri deleted the litellm_/wonderful-bouman branch April 18, 2026 16:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants