From d45c0d79e03108c2c08448336f9b200ddf6f43e9 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 13 Jun 2026 22:09:48 +0000 Subject: [PATCH] test(auth_v2): pin API-key role resolution fail-closed paths --- .../proxy/auth_v2/test_resolver.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/test_litellm/proxy/auth_v2/test_resolver.py b/tests/test_litellm/proxy/auth_v2/test_resolver.py index f381818d3ad..203b10a75e4 100644 --- a/tests/test_litellm/proxy/auth_v2/test_resolver.py +++ b/tests/test_litellm/proxy/auth_v2/test_resolver.py @@ -93,6 +93,32 @@ async def test_api_key_role_falls_back_to_owning_user(): assert principal.roles == [Role.PLATFORM_ADMIN] +async def test_api_key_role_fails_closed_when_owning_user_unresolvable(): + # key carries a user_id but no user_role, and the user cannot be resolved + # (cache miss + unusable prisma stub): the role lookup must fail closed to no + # role rather than raising or inheriting one + raw = "sk-live-orphan" + key = UserAPIKeyAuth(token=hash_token(raw), user_id="u-missing") + store = _store({hash_token(raw): key}) + + principal = await store.resolve(_api_key_credential(raw)) + + assert principal.user is not None and principal.user.id == "u-missing" + assert principal.roles == [] + + +async def test_service_account_key_without_user_has_no_role(): + # a key with no user_id never consults the user table and stays role-less + raw = "sk-live-svc" + key = UserAPIKeyAuth(token=hash_token(raw), key_alias="ci-bot") + store = _store({hash_token(raw): key}) + + principal = await store.resolve(_api_key_credential(raw)) + + assert principal.principal_type == PrincipalType.SERVICE_ACCOUNT + assert principal.roles == [] + + async def test_api_key_lookup_is_keyed_on_hashed_token(): raw = "sk-live-abc" key = UserAPIKeyAuth(token=hash_token(raw), user_id="u-1")