mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-11 22:51:28 +00:00
fix(auth): deny model access for teamless keys with all-team-models (#32022)
_enforce_key_and_fallback_model_access and can_key_call_resolved_model both unconditionally skipped key-level model checks whenever all-team-models was present, without verifying the key actually belongs to a team. PR #29746 fixed the listing path (get_key_models) but these two call-path checks were left untouched, letting teamless keys call any model via /chat/completions while seeing an empty model list. Add team_id is not None guard to both bypass conditions so teamless keys fall through to can_key_call_model, which already correctly rejects unresolvable all-team-models sentinels Co-authored-by: mateo <mateo@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
cbe23d6184
commit
dfbbda4f19
3 changed files with 60 additions and 2 deletions
|
|
@ -3017,7 +3017,9 @@ async def can_key_call_resolved_model(
|
|||
)
|
||||
|
||||
skip_key_model_check = valid_token.config or (
|
||||
isinstance(valid_token.models, list) and SpecialModelNames.all_team_models.value in valid_token.models
|
||||
isinstance(valid_token.models, list)
|
||||
and SpecialModelNames.all_team_models.value in valid_token.models
|
||||
and valid_token.team_id is not None
|
||||
)
|
||||
if not skip_key_model_check:
|
||||
await can_key_call_model(
|
||||
|
|
|
|||
|
|
@ -2676,7 +2676,11 @@ async def _enforce_key_and_fallback_model_access(
|
|||
model_list = config.get("model_list", [])
|
||||
new_model_list = model_list
|
||||
verbose_proxy_logger.debug(f"\n new llm router model list {new_model_list}")
|
||||
elif isinstance(valid_token.models, list) and "all-team-models" in valid_token.models:
|
||||
elif (
|
||||
isinstance(valid_token.models, list)
|
||||
and "all-team-models" in valid_token.models
|
||||
and valid_token.team_id is not None
|
||||
):
|
||||
pass
|
||||
else:
|
||||
model = _get_model_from_request_context(
|
||||
|
|
|
|||
|
|
@ -355,6 +355,58 @@ async def test_can_key_call_model_all_team_models_no_team_id_is_denied():
|
|||
assert exc_info.value.type == ProxyErrorTypes.key_model_access_denied
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_enforce_key_access_teamless_all_team_models_denied():
|
||||
"""_enforce_key_and_fallback_model_access must not skip key-level
|
||||
model checks for a teamless key that carries all-team-models."""
|
||||
from litellm.proxy._types import SpecialModelNames
|
||||
from litellm.proxy.auth.user_api_key_auth import (
|
||||
_enforce_key_and_fallback_model_access,
|
||||
)
|
||||
|
||||
valid_token = UserAPIKeyAuth(
|
||||
api_key="sk-orphan-key",
|
||||
models=[SpecialModelNames.all_team_models.value],
|
||||
team_models=[],
|
||||
)
|
||||
|
||||
with pytest.raises(ProxyException) as exc_info:
|
||||
await _enforce_key_and_fallback_model_access(
|
||||
valid_token=valid_token,
|
||||
request_data={"model": "gpt-4o"},
|
||||
route="/v1/chat/completions",
|
||||
request=None,
|
||||
llm_model_list=None,
|
||||
llm_router=None,
|
||||
)
|
||||
|
||||
assert exc_info.value.type == ProxyErrorTypes.key_model_access_denied
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_can_key_call_resolved_model_teamless_all_team_models_denied():
|
||||
"""can_key_call_resolved_model must not skip key-level model checks
|
||||
for a teamless key that carries all-team-models."""
|
||||
from litellm.proxy._types import SpecialModelNames
|
||||
from litellm.proxy.auth.auth_checks import can_key_call_resolved_model
|
||||
|
||||
valid_token = UserAPIKeyAuth(
|
||||
api_key="sk-orphan-key",
|
||||
models=[SpecialModelNames.all_team_models.value],
|
||||
team_models=[],
|
||||
)
|
||||
|
||||
with pytest.raises(ProxyException) as exc_info:
|
||||
await can_key_call_resolved_model(
|
||||
model="gpt-4o",
|
||||
llm_model_list=None,
|
||||
valid_token=valid_token,
|
||||
llm_router=None,
|
||||
)
|
||||
|
||||
assert exc_info.value.type == ProxyErrorTypes.key_model_access_denied
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_can_team_access_model_all_team_models_expands_router_models():
|
||||
from litellm import Router
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue