fix(proxy): enforce auth defaults for raw pass-through config

This commit is contained in:
lzhan011 2026-08-31 16:16:33 -05:00
parent 987ab76921
commit b69818f5ed
4 changed files with 78 additions and 3 deletions

View file

@ -2423,7 +2423,11 @@ async def _run_centralized_common_checks(
pass_through_endpoints: Final = general_settings.get("pass_through_endpoints", None)
if pass_through_endpoints is not None:
for endpoint in pass_through_endpoints:
if isinstance(endpoint, dict) and endpoint.get("path", "") == route and endpoint.get("auth") is not True:
if (
isinstance(endpoint, dict)
and endpoint.get("path", "") == route
and endpoint.get("auth", True) is not True
):
return
# No-auth dev mode: master_key unset AND no JWT/OAuth2 auth

View file

@ -3060,7 +3060,7 @@ async def _register_pass_through_endpoint(
forward_headers: Final = endpoint_data.get("forward_headers")
merge_query_params: Final = endpoint_data.get("merge_query_params")
default_query_params: Final = endpoint_data.get("default_query_params")
auth: Final[bool | str | None] = endpoint_data.get("auth")
auth: Final[bool | str | None] = endpoint_data.get("auth", True)
dependencies = None
auth_enforced: Final = auth is not None and str(auth).lower() == "true"

View file

@ -3834,6 +3834,50 @@ async def test_centralized_common_checks_runs_for_standard_auth():
setattr(_proxy_server_mod, k, v)
@pytest.mark.asyncio
async def test_centralized_common_checks_runs_for_raw_passthrough_without_auth():
import litellm.proxy.proxy_server as _proxy_server_mod
from fastapi import Request
from starlette.datastructures import URL
route = "/chat/completions"
token = UserAPIKeyAuth(api_key="sk-test")
request = Request(scope={"type": "http", "headers": []})
request._url = URL(url=route)
attrs = _proxy_attrs_for_centralized_checks(user_custom_auth=None)
attrs["general_settings"] = {
"reject_clientside_metadata_tags": True,
"pass_through_endpoints": [
{
"path": route,
"target": "https://example.com",
}
]
}
originals = {
attribute: getattr(_proxy_server_mod, attribute, None)
for attribute in attrs
}
try:
for attribute, value in attrs.items():
setattr(_proxy_server_mod, attribute, value)
with pytest.raises(ProxyException) as exc_info:
await _run_centralized_common_checks(
user_api_key_auth_obj=token,
request=request,
request_data={
"model": "gpt-4o",
"metadata": {"tags": ["client-supplied"]},
},
route=route,
)
finally:
for attribute, value in originals.items():
setattr(_proxy_server_mod, attribute, value)
assert exc_info.value.type == ProxyErrorTypes.bad_request_error
@pytest.mark.asyncio
@pytest.mark.parametrize(
"route",

View file

@ -25,11 +25,12 @@ import pytest
from fastapi import FastAPI
from litellm.proxy._types import PassThroughGenericEndpoint
from litellm.proxy._types import LiteLLMRoutes, PassThroughGenericEndpoint
from litellm.proxy.auth.user_api_key_auth import (
check_api_key_for_custom_headers_or_pass_through_endpoints,
)
from litellm.proxy.pass_through_endpoints.pass_through_endpoints import (
_registered_pass_through_routes,
_register_pass_through_endpoint,
)
@ -79,6 +80,32 @@ async def test_register_passthrough_with_auth_true_works_for_oss(monkeypatch):
)
@pytest.mark.asyncio
async def test_register_raw_passthrough_defaults_to_authentication():
path = "/raw-auth-default"
route_key = f"raw-auth-default:exact:{path}:GET"
endpoint: dict[str, object] = {
"id": "raw-auth-default",
"path": path,
"target": "https://example.com",
"methods": ["GET"],
}
try:
await _register_pass_through_endpoint(
endpoint=endpoint,
app=FastAPI(),
premium_user=False,
visited_endpoints=set(),
)
assert _registered_pass_through_routes[route_key]["auth"] is True
assert path in LiteLLMRoutes.openai_routes.value
finally:
_registered_pass_through_routes.pop(route_key, None)
if path in LiteLLMRoutes.openai_routes.value:
LiteLLMRoutes.openai_routes.value.remove(path)
@pytest.mark.asyncio
async def test_runtime_check_treats_missing_auth_key_as_authenticated():
# The runtime dispatch in user_api_key_auth pulls