fix(proxy): enforce organization boundaries in admin operations#25829
fix(proxy): enforce organization boundaries in admin operations#25829stuxf wants to merge 2 commits intoBerriAI:litellm_yj_apr15from
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Greptile SummaryThis PR fixes two related security issues in the proxy's organization boundary enforcement: (1) Confidence Score: 5/5Safe to merge — both security fixes are logically correct, well-tested, and limited in scope. All findings are P2 or lower. The two core behavioral changes ( No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/proxy/auth/auth_checks_organization.py | Changed _user_is_org_admin from any()-based loop to an all() set-membership check; correctly guards the empty-list vacuous-truth case that already existed. No issues. |
| litellm/proxy/management_endpoints/team_endpoints.py | Removed the not user_id guard in _build_team_list_where_conditions so org-scope filter is always applied; removed cross-org member-team fetch in legacy _authorize_and_filter_teams. Remaining diffs are Black-only reformatting. |
| tests/test_litellm/proxy/auth/test_route_checks.py | Adds test_org_admin_cannot_escalate_to_other_org and test_org_admin_of_multiple_orgs_can_operate_on_both regression tests; remaining changes are Black reformatting of existing tests. |
| tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py | Updates test_list_team_v2_org_admin_with_user_id_returns_user_teams assertion to expect both team_id and organization_id filters in the DB query, correctly reflecting the new behaviour. Remaining changes are Black reformatting. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Org admin calls /team/list or admin op] --> B{request includes\norganization_id / organizations?}
B -- No --> C[return False\n no orgs to act on]
B -- Yes --> D[Build admin_org_ids set\nfrom caller memberships]
D --> E{all candidate org IDs\n in admin_org_ids?}
E -- No --> F[Access Denied\ncross-org escalation blocked]
E -- Yes --> G[Build team list query]
G --> H{user_id filter\nprovided?}
H -- No --> I[WHERE organization_id IN admin_orgs\nReturn all org teams]
H -- Yes --> J[WHERE organization_id IN admin_orgs\nAND team_id IN user_teams\nReturns only org-scoped user teams]
J --> K[Result scoped to\ncaller's orgs only]
I --> K
Reviews (2): Last reviewed commit: "test: add regression tests for cross-org..." | Re-trigger Greptile
083a061 to
5fc71c2
Compare
Validate org admin role against all requested organizations instead of returning on first match. Scope team list queries to the caller's permitted organizations when filtering by user_id.
5fc71c2 to
86a7a54
Compare
Verify that an org admin of org-A cannot operate on org-B, and that an admin of both orgs can operate on both.
Relevant issues
Fixes inconsistent organization boundary checks in team listing and user creation flows.
Pre-Submission checklist
tests/test_litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewType
🐛 Bug Fix
Changes
1. Validate org admin role against all requested organizations
_user_is_org_admin()previously returnedTrueif the caller was admin of any one of the listed organizations. Now validates against all of them — an org admin of org-A cannot perform operations targeting org-B.2. Scope team list queries to caller's organizations
_build_team_list_where_conditions()previously dropped the organization filter when auser_idparameter was provided, returning teams across all organizations. Now always applies the org filter for org admins._authorize_and_filter_teams()(legacy path) previously fetched teams outside the caller's orgs if the target user was a member. Now only returns teams within the caller's permitted organizations.