Commit graph

13345 commits

Author SHA1 Message Date
mateo-berri
68db1c5e9e tests(vcr): switch to record_mode=new_episodes to avoid partial-cassette poisoning
record_mode='once' refused to add new requests once any cassette
existed in Redis. Combined with filter_non_2xx_response (which drops
non-2xx responses from the saved cassette) and a 24h shared-Redis TTL,
a single transient API failure mid-test left the cassette stuck with
only the leading non-API requests (e.g. the model_prices fetch from
raw.githubusercontent.com), and every subsequent run for the next 24h
errored with 'Can't overwrite existing cassette'.

new_episodes records anything not already present, so partially
populated cassettes recover on the next run instead of poisoning the
suite for a full TTL window.
2026-04-30 17:22:21 -07:00
user
00442e653c chore(sso): bind generic SSO state to a session cookie
The Generic SSO PKCE flow used the URL ``state`` parameter as the
cache key for the PKCE ``code_verifier`` without binding the state
to the caller's browser.  An attacker who pre-minted a state and
cached a verifier under it could hand the resulting login link to a
victim; the victim's auth code would then be exchanged with the
attacker's verifier on the callback, producing an access token
under the attacker's control (Login CSRF / token theft).

The non-PKCE branch is unaffected because it delegates to
fastapi-sso's ``verify_and_process``, which performs its own
session-cookie check.  The PKCE branch bypasses that helper, which
is exactly the gap this commit closes.

Two-part fix in ``ui_sso.py``:

- ``get_generic_sso_redirect_response`` now sets a
  ``litellm_oauth_state`` cookie (HttpOnly, SameSite=Lax, 10-min TTL)
  carrying the state value used in the redirect URL.  The cookie is
  set on the redirect response just like the existing
  ``litellm_cp_return_to`` cookie a few lines earlier in the file.
- ``get_generic_sso_response`` validates ``request.cookies.get(
  "litellm_oauth_state")`` against ``request.query_params.get(
  "state")`` via ``secrets.compare_digest`` before invoking the
  PKCE token exchange.  Mismatch (or either being missing) raises a
  ``ProxyException`` with HTTP 400.

The pre-existing TODO above the redirect logic ("state should be a
random string and added to the user session with cookie") is now
addressed and removed.

Tests cover the redirect-side cookie set, the missing-cookie reject
shape, the URL/cookie-mismatch reject shape, and the matching-cookie
happy path.
2026-05-01 00:19:13 +00:00
user
9db8ecac12 update budget reservation auth test expectation 2026-04-30 17:13:49 -07:00
yuneng-jiang
bdcc23853c
Merge pull request #26835 from stuxf/codex/cli-sso-flow-binding
chore(cli): tighten CLI SSO session flow
2026-04-30 17:10:27 -07:00
yuneng-jiang
15b7386859
Merge pull request #26815 from stuxf/fix/get-image-lfi-ssrf
chore(proxy): contain UI_LOGO_PATH / LITELLM_FAVICON_URL on unauthenticated asset endpoints
2026-04-30 17:10:15 -07:00
user
fce86d1334 fix budget reservation greptile findings 2026-04-30 17:08:45 -07:00
yuneng-jiang
71d5015975
Merge pull request #26827 from stuxf/fix/passthrough-auth-default
chore(passthrough): default auth=True and drop enterprise gate on the safe option
2026-04-30 17:06:37 -07:00
Yuneng Jiang
be0e9914dc
[Test] Proxy E2E: Opt In To Client Mock Response For Model Access Tests
The proxy's ingress hardening (commit 842eea0131) now strips client-supplied
`mock_response` from the request body unless the calling key or team has the
`allow_client_mock_response: true` admin-metadata flag set. The e2e model
access tests rely on `mock_response` to short-circuit the LLM call, so without
the flag they hit real backends — the bedrock wildcard route fakes out to a
shared example endpoint that now 404s on unsupported paths, causing
`test_model_access_patterns[key_models2-bedrock/anthropic.claude-3-True]`
(and the bedrock/anthropic.* row that pytest -x never reaches) to fail.

Set `allow_client_mock_response: true` on every key and team this test file
provisions so `mock_response` is preserved end-to-end.
2026-04-30 17:05:31 -07:00
user
2922da9b64 test(vector stores): cover azure passthrough guard 2026-04-30 17:00:43 -07:00
user
f8d187785d finalize invalidated budget reservations 2026-04-30 16:52:09 -07:00
Michael Riad Zaky
053e040171 run pre_call_hook on Google generateContent endpoints 2026-04-30 16:43:42 -07:00
user
32272908d3 test(vector stores): isolate provider-native guard case 2026-04-30 16:41:13 -07:00
mateo-berri
468b849072
tests(vcr): drop YAML/cassettes-directory metaphor from Redis keys 2026-04-30 23:37:17 +00:00
user
49ccb3369c test(vector stores): pin rag scan depth boundary 2026-04-30 16:33:42 -07:00
user
e034935b53 fix budget reservation window fallback races 2026-04-30 16:26:43 -07:00
user
1201a0ba5c test(vector stores): pin no-db registry fallback case 2026-04-30 16:16:37 -07:00
Michael Riad Zaky
47b2832d6f test: replace subprocess startup-import diff with static source scan 2026-04-30 16:15:46 -07:00
user
1373ae1021 fix budget tag spend counter reconciliation 2026-04-30 16:09:38 -07:00
user
ce0c557012 chore(vector stores): address access review followups 2026-04-30 16:09:26 -07:00
mateo-berri
f55a710e92
tests(vcr): accept REDIS_URL / REDIS_SSL_URL for managed Redis with TLS 2026-04-30 23:08:01 +00:00
mateo-berri
59d5901766
tests(vcr): allow playback repeats so duplicate intra-test requests serve from cache 2026-04-30 22:57:21 +00:00
mateo-berri
73594262ee
tests(vcr): drop redundant num_retries=3 layer for vcr-marked tests
Provider SDKs already retry transient 5xx/429 with exponential backoff
(default max_retries=2), and pytest.mark.flaky covers test-level
retries on top of that. Setting litellm.num_retries=3 here just
multiplied the existing layers — worst case 6 (flaky) x 3 (this) x
2 (CI rerunfailures) = 36 attempts on a single test.

Removing it keeps SDK-level network-blip protection intact and
shortens worst-case latency on cache-miss runs.
2026-04-30 22:42:30 +00:00
user
363c0de6f7 chore(vector stores): address tenant guard followups 2026-04-30 15:13:24 -07:00
user
d3ab59e059 chore(vector stores): tighten managed store access 2026-04-30 15:04:25 -07:00
user
96a283ed0f guard reservation invalidation cleanup 2026-04-30 15:00:35 -07:00
michelligabriele
0f98f3754f
fix(proxy): reject user_id=None on non-admin analytics endpoints (cross-tenant disclosure) 2026-04-30 23:54:01 +02:00
user
8311456cfc invalidate reservations after release cleanup failure 2026-04-30 14:48:55 -07:00
mateo-berri
e1f2b4b818
tests(vcr): trim non-load-bearing comments and docstrings
Removes commentary that restated the code, including:

- module-level banners explaining what the conftest does (covered by
  Readme.md and the function bodies)
- docstrings on _scrub_response, _before_record_response, vcr_config,
  _vcr_disabled, pytest_recording_configure (function names + bodies
  are self-evident)
- inline notes about header filtering, match_on, etc.
- per-test docstrings restating the test name

Keeps the two non-obvious notes that aren't recoverable from the code:
the vcrpy/respx httpx-transport collision rationale on
_RESPX_CONFLICTING_FILES, the vcrpy "return None to skip persisting"
contract on filter_non_2xx_response, and the fixture-ordering
dependency on _vcr_record_retries.
2026-04-30 21:48:48 +00:00
user
3800596d08 fix(proxy): stabilize lazy openapi snapshot ids 2026-04-30 14:42:50 -07:00
mateo-berri
c7d647b567
tests: drop YAML cassettes, make Redis-backed VCR the default
Removes the YAML cassette feature entirely and replaces it with a
Redis-only flow. Every test in tests/llm_translation/ and
tests/llm_responses_api_testing/ is auto-marked @pytest.mark.vcr via
conftest.pytest_collection_modifyitems, so any provider call lands in
the Redis cache (litellm:vcr:cassette:<rel_path>, 24h TTL). First run
records, runs within the day replay, day rollover re-records and
surfaces upstream API drift within 24h.

VCR is on by default. Set LITELLM_VCR_DISABLE=1, or simply leave
REDIS_HOST unset, to opt out — both bypass the auto-marker entirely so
nothing about cassettes runs. record_mode is "once" so cache-miss
records and cache-hit replays.

The 8 existing respx-using files in tests/llm_translation are excluded
from the auto-marker (vcrpy and respx both patch the httpx transport;
applying both makes one silently win). The persister's own unit-test
file is also excluded so it doesn't recursively run inside a cassette.

The persister moved from tests/llm_translation/_vcr_redis_persister.py
to tests/_vcr_redis_persister.py so both conftests share it. The two
demo tests in test_anthropic_completion_vcr.py were ported into
test_anthropic_completion.py and the demo file was deleted.

Adds tests/_flush_vcr_cache.py + a Make target
(test-llm-translation-flush-vcr-cache) that scans
litellm:vcr:cassette:* and pipelines DELETEs, for the
"I want the next CI run to re-record now" workflow. Drops the now-dead
test-llm-translation-record target.

Provider keys are still required on cache-miss (which happens on first
run and once a day after that). Replay-mode runs need only Redis.
2026-04-30 21:40:58 +00:00
user
719e891c3a coalesce malformed window reservation seeding 2026-04-30 14:38:37 -07:00
user
bb6d7c9715 fix(callbacks): preserve langfuse secret alias 2026-04-30 14:36:51 -07:00
user
258edac727 test(callbacks): cover upstream langfuse debug env 2026-04-30 14:34:39 -07:00
mateo-berri
46ba48e69a
fix(router): apply decoded provider for managed container IDs without model_id
Some checks failed
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
A managed cntr_ ID can encode a non-OpenAI provider (e.g. azure) with an
empty model_id when streaming events have no router model_info.id. The
provider override was nested inside 'if model_id:', so such IDs unwrapped
the container_id but kept custom_llm_provider='openai', routing the
request to the wrong upstream. Hoist the override out of the model_id
guard.
2026-04-30 21:29:38 +00:00
user
15d4d51453 chore(callbacks): guard dynamic integration hosts 2026-04-30 14:27:19 -07:00
user
5521af096e preserve database failure during reservation cleanup 2026-04-30 14:23:57 -07:00
user
0b71282985 address budget reservation review findings 2026-04-30 14:06:42 -07:00
user
87849b74b9 test(gemini): cover decoded delete file names 2026-04-30 14:03:54 -07:00
user
46183e6dc9 Merge remote-tracking branch 'origin/litellm_internal_staging' into codex/budget-race-enforcement-snapshot 2026-04-30 13:56:16 -07:00
user
19f8c1013b fix(gemini): validate fully decoded file names 2026-04-30 13:50:15 -07:00
user
0794ae67be avoid direct budget reservation db lookups 2026-04-30 13:49:59 -07:00
yuneng-jiang
256e05e474
Merge pull request #26849 from stuxf/fix/mcp-oauth-discovery-ssrf
chore(mcp): SSRF guard on OAuth metadata discovery follow-up fetches
2026-04-30 13:44:16 -07:00
yuneng-jiang
174c770b07
Merge pull request #26836 from stuxf/fix/byok-credential-encryption
chore(mcp): encrypt user-scoped MCP credentials at rest
2026-04-30 13:42:57 -07:00
user
6ca6220679 chore(proxy): split lazy openapi multi-method routes 2026-04-30 13:41:38 -07:00
user
ca50868b75 harden end-user and tag budget reservations 2026-04-30 13:37:10 -07:00
mateo-berri
33a051636d
tests(llm_translation): add Redis cassette persister with 24h TTL
Stores VCR cassettes in Redis under litellm:vcr:cassette:<rel_path> with
a 24h expiry instead of YAML on disk. The TTL means each daily CI run
starts with an aged-out cache, naturally re-records against live providers,
and surfaces upstream API drift within a day without a manual `make`
re-record sweep. Opt-in via LITELLM_VCR_REDIS=1; default behaviour is
unchanged so local dev keeps the on-disk cassettes.

before_record_response now drops non-2xx responses so a transient 5xx or
429 from a provider can't poison the cache for the rest of the TTL window.
Vcr-marked tests bump litellm.num_retries to 3 during recording so
provider-SDK exponential backoff kicks in on the cache-miss path.

Tests cover the three surfaces we depend on in CI: serialize/deserialize
roundtrip via the real vcrpy serializer, TTL is actually applied to saved
keys, cache miss raises CassetteNotFoundError so vcrpy falls through to
record mode, and 2xx-only filtering across the status-code matrix
(2xx kept, 3xx/4xx/5xx dropped, with 429 and 503 explicitly pinned).
2026-04-30 20:28:11 +00:00
user
e1f39674f3 Merge remote-tracking branch 'origin/litellm_internal_staging' into codex/provider-url-destination-guard 2026-04-30 13:20:44 -07:00
user
d75f62a17c chore(providers): add guarded URL model migration path 2026-04-30 13:17:09 -07:00
yuneng-jiang
4ff8f0e901
Merge pull request #26851 from stuxf/codex/fix-callback-env-secret-resolution
chore(proxy): block env callback refs in key metadata
2026-04-30 13:11:32 -07:00
yuneng-jiang
aa76ab2df7
Merge pull request #26862 from stuxf/codex/control-field-sanitization
chore(proxy): harden request control fields
2026-04-30 13:10:58 -07:00