diff --git a/litellm/proxy/auth/auth_checks.py b/litellm/proxy/auth/auth_checks.py index dc693317de0..ee2cc68ad7c 100644 --- a/litellm/proxy/auth/auth_checks.py +++ b/litellm/proxy/auth/auth_checks.py @@ -4031,7 +4031,7 @@ def _can_object_call_model( return True raise ProxyException( - message=f"{object_type} not allowed to access model. This {object_type} can only access models={models}. Tried to access {model}", + message=f"{object_type} not allowed to access model. Tried to access {model}", type=ProxyErrorTypes.get_model_access_error_type_for_object(object_type=object_type), param="model", code=status.HTTP_403_FORBIDDEN, diff --git a/litellm/proxy/auth/user_api_key_auth.py b/litellm/proxy/auth/user_api_key_auth.py index 93293db24c6..c66041b01ec 100644 --- a/litellm/proxy/auth/user_api_key_auth.py +++ b/litellm/proxy/auth/user_api_key_auth.py @@ -1907,7 +1907,7 @@ async def _user_api_key_auth_builder( ) except ProxyException as e: if e.code == 401 or e.code == "401": - e.message = f"Authentication Error, Invalid proxy server token passed. Received API Key = {abbreviated_api_key}, Key Hash (Token) ={api_key}. Unable to find token in cache or `LiteLLM_VerificationTokenTable`" + e.message = f"Authentication Error, Invalid proxy server token passed. Received API Key = {abbreviated_api_key}, Unable to find token in cache or `LiteLLM_VerificationTokenTable`" raise e # update end-user params on valid token # These can change per request - it's important to update them here diff --git a/tests/proxy_unit_tests/test_auth_checks.py b/tests/proxy_unit_tests/test_auth_checks.py index d436c99cd20..33ae3bb7bc7 100644 --- a/tests/proxy_unit_tests/test_auth_checks.py +++ b/tests/proxy_unit_tests/test_auth_checks.py @@ -163,7 +163,7 @@ async def test_can_key_call_model(model, expect_to_work): if expect_to_work: await can_key_call_model(**args) else: - with pytest.raises(Exception, match='key not allowed to access model\\. This key can only access') as e: + with pytest.raises(Exception, match='key not allowed to access model\\. Tried to access') as e: await can_key_call_model(**args) print(e) @@ -943,7 +943,7 @@ async def test_can_key_call_model_with_aliases(model, alias_map, expect_to_work) llm_router=router, ) else: - with pytest.raises(Exception, match='key not allowed to access model\\. This key can only access') as e: + with pytest.raises(Exception, match='key not allowed to access model\\. Tried to access') as e: await can_key_call_model( model=model, llm_model_list=llm_model_list, diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_sampling_model_access.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_sampling_model_access.py index f141cb2e316..a3708215ff5 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_sampling_model_access.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_sampling_model_access.py @@ -123,7 +123,7 @@ class TestCheckModelAccess: "litellm.proxy.auth.auth_checks.can_key_call_model", new_callable=AsyncMock, side_effect=ProxyException( - message="key not allowed to access model. This key can only access models=['gpt-3.5-turbo']. Tried to access claude-3-opus-20240229", + message="key not allowed to access model. Tried to access claude-3-opus-20240229", type="key_model_access_denied", param="model", code=401, diff --git a/tests/test_litellm/proxy/auth/test_auth_checks.py b/tests/test_litellm/proxy/auth/test_auth_checks.py index 2284a05b2e9..f937e54d9c3 100644 --- a/tests/test_litellm/proxy/auth/test_auth_checks.py +++ b/tests/test_litellm/proxy/auth/test_auth_checks.py @@ -7462,3 +7462,20 @@ async def test_enforced_model_allowlists_reads_every_level_from_cache(): ] assert [list(scope) for scope in personal] == [[], [], [], ["o3"], []] assert [list(scope) for scope in without_database] == [["gpt-4o"], ["gpt-4o-mini"]] + +def test_model_access_denied_does_not_leak_allowlist(): + """Verify 403 error does not expose the full model allowlist (#40217).""" + import pytest + from litellm.proxy.auth.auth_checks import _can_object_call_model + from litellm.proxy.utils import ProxyException + + with pytest.raises(ProxyException) as exc_info: + _can_object_call_model( + model="gpt-4o", + llm_router=None, + models=["gpt-3.5-turbo", "claude-3-5-sonnet"], + object_type="key" + ) + assert str(exc_info.value.code) == "403" + assert "models=" not in exc_info.value.message + assert "Tried to access gpt-4o" in exc_info.value.message