Skip to content

chore(proxy): cherry-pick #28547 onto patch/v1.85.1 - #28968

Merged
yuneng-berri merged 3 commits into
patch/v1.85.1from
litellm_yj/cherry-pick-28547-v1.85.1
May 27, 2026
Merged

chore(proxy): cherry-pick #28547 onto patch/v1.85.1#28968
yuneng-berri merged 3 commits into
patch/v1.85.1from
litellm_yj/cherry-pick-28547-v1.85.1

Conversation

@yuneng-berri

Copy link
Copy Markdown
Collaborator

Backport of #28547 (d480ffda3c) onto patch/v1.85.1.

Routes the remaining path-dependent call sites in auth, ACL, routing, and audit-log decisions through get_request_route(request) so they read from the ASGI scope["path"] instead of request.url.path. The helper itself already exists on v1.85.1 (added by #27878); this PR extends the helper's usage to the additional sites listed below.

Sites routed through get_request_route

  • _experimental/mcp_server/auth/user_api_key_auth_mcp.py
  • management_endpoints/mcp_management_endpoints.py
  • vector_store_endpoints/utils.py
  • pass_through_endpoints/pass_through_endpoints.py
  • auth/route_checks.py
  • litellm_pre_call_utils.py
  • spend_tracking/spend_management_endpoints.py
  • common_utils/http_parsing_utils.py
  • management_helpers/utils.py
  • health_endpoints/_health_endpoints.py

Conflict resolution

Cherry-pick applied cleanly with no conflicts. All 11 files plus the test file are pure request.url.pathget_request_route(request) swaps with the lazy auth_utils import (no feature drift).

Test plan

  • uv run pytest tests/proxy_unit_tests/test_proxy_routes.py -v
  • make test-unit

Backport of #28547 (`d480ffda3c`) onto the `patch/v1.85.1` branch.

Routes the remaining path-dependent call sites in auth, ACL, routing,
and audit-log decisions through `get_request_route(request)` so they
read from the ASGI `scope["path"]` instead of `request.url.path`. The
helper itself already exists on v1.85.1 (added by #27878); this PR
extends the helper's usage to the additional sites listed below.

Sites routed through get_request_route:
- _experimental/mcp_server/auth/user_api_key_auth_mcp.py
- management_endpoints/mcp_management_endpoints.py
- vector_store_endpoints/utils.py
- pass_through_endpoints/pass_through_endpoints.py
- auth/route_checks.py
- litellm_pre_call_utils.py
- spend_tracking/spend_management_endpoints.py
- common_utils/http_parsing_utils.py
- management_helpers/utils.py
- health_endpoints/_health_endpoints.py

Regression tests in tests/proxy_unit_tests/test_proxy_routes.py
construct a Request with scope["path"] set to a benign route and the
Host header crafted so url.path would resolve differently; each
site's decision is asserted against scope["path"].

Conflict resolution
-------------------

Cherry-pick applied cleanly with no conflicts. All 11 files plus the
test file are pure `request.url.path` → `get_request_route(request)`
swaps with the lazy auth_utils import (no feature drift).
@greptile-apps

greptile-apps Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This cherry-pick from #28547 closes a Host-header path-smuggling gap on the patch/v1.85.1 branch: Starlette's request.url.path re-parses the URL using the Host header, so a crafted value like localhost/?x=1 collapses the path to "/", which could flip auth, ACL, and routing decisions. The fix routes all remaining call sites through the already-existing get_request_route(request) helper, which reads the authoritative route from scope["path"] (uvicorn's parse of the HTTP request line).

  • 10 call sites migrated across auth, MCP, vector-store ACL, pass-through, spend-log, and OTel audit-log paths — all mechanical request.url.pathget_request_route(request) swaps with inline imports to avoid the proxy import cycle.
  • Tests extended with 7 new parametric cases in test_proxy_routes.py that construct requests with malformed Host headers and assert each call site resolves the route from the ASGI scope rather than the (manipulable) URL.

Confidence Score: 5/5

Safe to merge — all changes are targeted substitutions of a single helper call with no logic additions or removals, and the test file gains coverage without weakening any existing assertions.

Every changed line is a direct swap of request.url.path for get_request_route(request), a helper already tested and used on this branch since #27878. The cherry-pick applied cleanly, inline imports are correctly scoped and consistently documented, and the dropped or '' guard in the MCP management endpoint is safe because get_request_route always returns a str. The new tests exercise the exact bypass vectors described in the PR and do not relax any pre-existing assertions.

No files require special attention.

Important Files Changed

Filename Overview
litellm/proxy/auth/auth_utils.py Updated docstring for get_request_route to explain the ASGI scope-vs-url.path security rationale; no logic changes.
litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py Replaces three request.url.path usages with get_request_route for /.well-known/ bypass guard and OAuth2 path checks; inline import added for cycle safety.
litellm/proxy/auth/route_checks.py _is_assistants_api_request now reads route from scope["path"] via get_request_route instead of request.url.path.
litellm/proxy/management_endpoints/mcp_management_endpoints.py PKCE token-endpoint detection now uses get_request_route; the original (request.url.path or "") None-guard is dropped since get_request_route always returns str.
litellm/proxy/management_helpers/utils.py Two OTel audit-log call sites that assigned _route from request.url.path now use get_request_route.
litellm/proxy/litellm_pre_call_utils.py _get_metadata_variable_name path check (thread/assistant detection) migrated to get_request_route.
litellm/proxy/common_utils/http_parsing_utils.py _add_vector_store_id_from_path now extracts vector_store_id from scope path rather than url.path.
litellm/proxy/vector_store_endpoints/utils.py Four endpoint-match calls use scope path for ACL decisions in both vector-store and vector-store-files permission checks.
litellm/proxy/spend_tracking/spend_management_endpoints.py ui_view_spend_logs v2-path detection migrated to get_request_route.
litellm/proxy/pass_through_endpoints/pass_through_endpoints.py create_pass_through_route inner handler path variable now reads from scope.
litellm/proxy/health_endpoints/_health_endpoints.py test_endpoint diagnostic route-echo updated to use get_request_route.
tests/proxy_unit_tests/test_proxy_routes.py Adds 7 new parametric test cases covering each migrated call site; only reformats the existing malformed-Host test, no assertion weakening.

Reviews (1): Last reviewed commit: "chore(proxy): cherry-pick #28547 onto pa..." | Re-trigger Greptile

@codecov

codecov Bot commented May 27, 2026

Copy link
Copy Markdown

@yuneng-berri
yuneng-berri merged commit 64cff6e into patch/v1.85.1 May 27, 2026
33 of 49 checks passed
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