From 56d0f953f5cbc5ec188d44d44d1cdcef1c6e5341 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 16:33:41 +0000 Subject: [PATCH 1/2] fix(proxy): list directly assigned team models in model access errors Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/proxy/auth/auth_checks.py | 2 +- .../proxy/auth/test_auth_checks.py | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/litellm/proxy/auth/auth_checks.py b/litellm/proxy/auth/auth_checks.py index 6d61ad4d3e8..f877e9a10db 100644 --- a/litellm/proxy/auth/auth_checks.py +++ b/litellm/proxy/auth/auth_checks.py @@ -4659,7 +4659,7 @@ async def can_team_access_model( return _can_object_call_model( model=model, llm_router=llm_router, - models=models_from_groups, + models=list(dict.fromkeys([*(team_object.models if team_object else []), *models_from_groups])), team_model_aliases=team_model_aliases, team_id=team_object.team_id if team_object else None, object_type="team", diff --git a/tests/test_litellm/proxy/auth/test_auth_checks.py b/tests/test_litellm/proxy/auth/test_auth_checks.py index 5f87f2def93..d677e6478c1 100644 --- a/tests/test_litellm/proxy/auth/test_auth_checks.py +++ b/tests/test_litellm/proxy/auth/test_auth_checks.py @@ -513,6 +513,31 @@ async def test_can_team_access_model_all_team_models_expands_router_models(): assert exc_info.value.type == ProxyErrorTypes.team_model_access_denied +@pytest.mark.asyncio +async def test_can_team_access_model_error_lists_direct_and_access_group_models(): + from litellm.proxy.auth.auth_checks import can_team_access_model + + team_object = LiteLLM_TeamTable( + team_id="team-123", + models=["direct-model"], + access_group_ids=["ag-1"], + ) + + with patch( + "litellm.proxy.auth.auth_checks._get_models_from_access_groups", + new=AsyncMock(return_value=["group-model"]), + ): + assert await can_team_access_model("direct-model", team_object, None) is True + assert await can_team_access_model("group-model", team_object, None) is True + + with pytest.raises(ProxyException) as exc_info: + await can_team_access_model("blocked-model", team_object, None) + + assert exc_info.value.type == ProxyErrorTypes.team_model_access_denied + assert "direct-model" in exc_info.value.message + assert "group-model" in exc_info.value.message + + @pytest.mark.asyncio async def test_get_key_object_should_reconnect_once_on_db_connection_error(): mock_prisma_client = MagicMock() From 79450121f828c0b4664855ecc2b25b29c53efa84 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 17:00:11 +0000 Subject: [PATCH 2/2] test(proxy): document access group test seam Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- tests/test_litellm/proxy/auth/test_auth_checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_litellm/proxy/auth/test_auth_checks.py b/tests/test_litellm/proxy/auth/test_auth_checks.py index d677e6478c1..78acc33165f 100644 --- a/tests/test_litellm/proxy/auth/test_auth_checks.py +++ b/tests/test_litellm/proxy/auth/test_auth_checks.py @@ -523,7 +523,7 @@ async def test_can_team_access_model_error_lists_direct_and_access_group_models( access_group_ids=["ag-1"], ) - with patch( + with patch( # test-quality-ok: access-group lookup has no dependency-injection seam "litellm.proxy.auth.auth_checks._get_models_from_access_groups", new=AsyncMock(return_value=["group-model"]), ):