From 5699aa5798b86392d48e2894153a3703b7bde462 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 11 Sep 2026 01:09:28 +0000 Subject: [PATCH] refactor(proxy): reuse loaded key row for team admin check Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../key_management_endpoints.py | 18 ++++++++++++++---- .../test_key_management_endpoints.py | 8 -------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/litellm/proxy/management_endpoints/key_management_endpoints.py b/litellm/proxy/management_endpoints/key_management_endpoints.py index 6ddb51490c3..d621b9f4bc7 100644 --- a/litellm/proxy/management_endpoints/key_management_endpoints.py +++ b/litellm/proxy/management_endpoints/key_management_endpoints.py @@ -2702,13 +2702,23 @@ async def _validate_update_key_caller_access( premium_user=premium_user, ) return - await _check_key_admin_access( - user_api_key_dict=user_api_key_dict, - hashed_token=existing_key_row.token, + team_obj: Final = await get_team_object( + team_id=existing_key_row.team_id, prisma_client=prisma_client, user_api_key_cache=user_api_key_cache, - route="/key/update", + check_db_only=True, ) + if team_obj is None or not ( + _is_user_team_admin(user_api_key_dict=user_api_key_dict, team_obj=team_obj) + or await _is_user_org_admin_for_team(user_api_key_dict=user_api_key_dict, team_obj=team_obj) + ): + raise HTTPException( + status_code=403, + detail={ + "error": f"Only proxy admins, team admins, or org admins can call /key/update. " + f"user_role={user_api_key_dict.user_role}, user_id={user_api_key_dict.user_id}" + }, + ) _check_model_access_group( models=data.models, llm_router=llm_router, diff --git a/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py index 21743e149d2..f8e3955c3dd 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py @@ -10916,10 +10916,6 @@ async def test_update_key_team_member_cannot_change_budget(monkeypatch): @pytest.mark.asyncio async def test_update_key_team_admin_can_change_budget_of_member_key(monkeypatch): - """A team admin (role="admin" in members_with_roles) can update max_budget - on a team key owned by another member. Previously the caller-vs-owner - check in common_key_access_checks rejected this with 403 before the - team-admin path was reached.""" from litellm.proxy.management_endpoints.key_management_endpoints import ( update_key_fn, ) @@ -11027,10 +11023,6 @@ async def test_update_key_team_admin_can_change_budget_of_member_key(monkeypatch async def test_update_key_non_admin_team_member_cannot_update_other_members_key( monkeypatch, ): - """A non-admin team member with /key/update in member_permissions still - cannot update another member's key (budget or otherwise): the - _check_key_admin_access path requires team/org admin for keys owned by - someone else.""" from litellm.proxy.management_endpoints.key_management_endpoints import ( update_key_fn, )