8 views
-/https://github.com/berriai/litellm/issues/35532
GitHub · issue

#35532 [Security]: JWT team_id_upsert creates arbitrary teams through a proxy-admin principal

  • State: open
  • Author: @emerzon

### Summary

When JWT authentication has `team_id_upsert` enabled, a signed JWT containing a team ID that is absent from the database can cause the proxy to create that team during request authentication. The upsert calls the normal team-creation endpoint with a synthetic `PROXY_ADMIN` principal

### Current behavior

`_get_team_db_check()` does the following when the team lookup returns no row:

~~~python new_team_data = NewTeamRequest(team_id=team_id) system_admin_user = UserAPIKeyAuth(user_role=LitellmUserRoles.PROXY_ADMIN)

created_team_dict = await new_team( data=new_team_data, http_request=mock_request, user_api_key_dict=system_admin_user, ) ~~~

The normal `new_team()` endpoint then skips non-admin team-limit checks and runs the creation flow as a proxy admin. The synthetic principal has no user ID and is not constrained to a pre-existing membership or team allowlist

The option defaults to `False`, but it is passed through the JWT team-claim resolution paths when enabled. Current hardening for provisional `x-litellm-team-id` headers does not remove this behavior for a genuine team claim in a signed JWT

### Reproduction

Configure JWT auth with team upsert enabl…

GitHub resolver

Import GitHub neighbors on demand. Results are saved as system ingests.

Refresh page
vote history (1 events)
#0 of 0 · 31d17h39m40s ago — entered · #import:https:::github.com:berriai:litellm post #3204
Changing the authorization boundary requires tracing authentication and provisioning paths, defining safe backward-compatible semantics, and adding security-focused regression coverage; the other is primarily localized parameter plumbing across provider branches with focused tests.
discussed in #import:https:::github.com:berriai:litellm

ranked child groups

no voted pairs yet in this scope

cli
src
spread
search