chore(proxy): cherry-pick #28547 onto patch/v1.85.1 - #28968
Conversation
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 SummaryThis cherry-pick from #28547 closes a Host-header path-smuggling gap on the
Confidence Score: 5/5Safe 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.
|
| 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 Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Backport of #28547 (
d480ffda3c) ontopatch/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 ASGIscope["path"]instead ofrequest.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.pymanagement_endpoints/mcp_management_endpoints.pyvector_store_endpoints/utils.pypass_through_endpoints/pass_through_endpoints.pyauth/route_checks.pylitellm_pre_call_utils.pyspend_tracking/spend_management_endpoints.pycommon_utils/http_parsing_utils.pymanagement_helpers/utils.pyhealth_endpoints/_health_endpoints.pyConflict 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 lazyauth_utilsimport (no feature drift).Test plan
uv run pytest tests/proxy_unit_tests/test_proxy_routes.py -vmake test-unit