Skip to content

[Fix] Tighten api_key value check in credential validation#25917

Merged
yuneng-berri merged 2 commits intolitellm_yj_apr16from
litellm_xpass_header_restriction
Apr 16, 2026
Merged

[Fix] Tighten api_key value check in credential validation#25917
yuneng-berri merged 2 commits intolitellm_yj_apr16from
litellm_xpass_header_restriction

Conversation

@yuneng-berri
Copy link
Copy Markdown
Collaborator

Summary

check_complete_credentials() previously checked only for the presence of the api_key key in the request body, without verifying the value. This allowed the check to pass with an empty string or null value, causing is_request_body_safe() to treat the request as providing client-side credentials and skip its parameter validation.

The fix verifies that the api_key value is a non-empty, non-whitespace string before considering credentials complete.

Changes

Updated check_complete_credentials() in litellm/proxy/auth/auth_utils.py to inspect the value of api_key rather than just its presence in the request body.

Testing

  • Verified the fix against a live proxy: empty string, null, and whitespace-only api_key values now result in proxy-level rejection when api_base is present.
  • Existing adjacent behavior (normal requests, real api_key passthrough) unaffected.
  • uv run pytest tests/test_litellm/proxy/auth/test_auth_utils.py — 45 passed
  • uv run pytest tests/proxy_unit_tests/test_proxy_utils.py -k "request_body_safe" — 4 passed

Type

🐛 Bug Fix
✅ Test

Relevant issues

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Apr 16, 2026 11:10pm

Request Review

@yuneng-berri yuneng-berri temporarily deployed to integration-postgres April 16, 2026 23:01 — with GitHub Actions Inactive
@yuneng-berri yuneng-berri changed the base branch from litellm_internal_staging to litellm_yj_apr16 April 16, 2026 23:02
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 16, 2026

Greptile Summary

This PR fixes a security bypass in check_complete_credentials() where the presence of an api_key key in the request body (regardless of its value) was treated as providing complete credentials, allowing empty string, null, or whitespace-only values to skip the api_base safety check in is_request_body_safe(). The fix validates that the value is a non-empty, non-whitespace string before returning True, and adds parametrized tests for the fixed edge cases.

Confidence Score: 5/5

Safe to merge — the fix is minimal, correct, and well-tested with no regressions.

The logic change is narrow and correct: short-circuit evaluation ensures no AttributeError on None, and the three-part guard (truthy and isinstance(str) and strip()) properly rejects all bypass values. The prior concern about missing tests has been resolved by the new parametrized test covering all documented bypass cases. No P0 or P1 findings remain.

No files require special attention.

Important Files Changed

Filename Overview
litellm/proxy/auth/auth_utils.py Tightened check_complete_credentials to validate the api_key value (non-empty, non-whitespace string) instead of only checking key presence; logic is correct and handles all bypass cases.
tests/proxy_unit_tests/test_proxy_utils.py Adds parametrized test_check_complete_credentials_api_key_values covering valid key, empty string, None, and whitespace-only cases; no real network calls, in correct test folder.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Incoming Request Body] --> B{api_base / base_url\nin request body?}
    B -- No --> Z[Request Safe ✓]
    B -- Yes --> C[check_complete_credentials]
    C --> D{model present?}
    D -- No --> E[return False]
    D -- Yes --> F{complex provider?\nsagemaker/bedrock/vertex}
    F -- Yes --> E
    F -- No --> G{api_key value is\nnon-empty string?}
    G -- No --> E[return False]
    G -- Yes --> H[return True\nCredentials complete]
    E --> I{allow_client_side_credentials\nor model-level config?}
    I -- Yes --> Z
    I -- No --> X[Raise ValueError\nRequest Rejected ✗]
    H --> Z
Loading

Reviews (2): Last reviewed commit: "test: add parametrized tests for api_key..." | Re-trigger Greptile

Comment on lines +72 to 76
api_key_value = request_body.get("api_key")
if api_key_value and isinstance(api_key_value, str) and api_key_value.strip():
return True

return False
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No new tests for the fixed edge cases

The check_complete_credentials() fix closes a real bypass (empty string, null, whitespace-only api_key), but the test suite (test_auth_utils.py and test_proxy_utils.py) has no new parametrized cases that directly call check_complete_credentials with these inputs. The existing is_request_body_safe tests only exercise the api_base path without an api_key field at all.

Per the project's testing policy ("Always add tests"), it's worth adding at least:

@pytest.mark.parametrize("bad_key", ["", None, "   ", "\t\n", 0, False])
def test_check_complete_credentials_rejects_missing_key_value(bad_key):
    from litellm.proxy.auth.auth_utils import check_complete_credentials
    body = {"model": "gpt-3.5-turbo", "api_base": "http://evil.com", "api_key": bad_key}
    assert check_complete_credentials(body) is False

def test_check_complete_credentials_accepts_valid_key():
    from litellm.proxy.auth.auth_utils import check_complete_credentials
    body = {"model": "gpt-3.5-turbo", "api_base": "http://valid.com", "api_key": "sk-real-key"}
    assert check_complete_credentials(body) is True

@yuneng-berri yuneng-berri temporarily deployed to integration-postgres April 16, 2026 23:08 — with GitHub Actions Inactive
@yuneng-berri yuneng-berri temporarily deployed to integration-postgres April 16, 2026 23:10 — with GitHub Actions Inactive
@yuneng-berri yuneng-berri temporarily deployed to integration-postgres April 16, 2026 23:10 — with GitHub Actions Inactive
@yuneng-berri yuneng-berri merged commit 1cd3ea8 into litellm_yj_apr16 Apr 16, 2026
95 of 99 checks passed
@yuneng-berri yuneng-berri deleted the litellm_xpass_header_restriction branch April 16, 2026 23:39
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.

1 participant