Skip to content

chore(release): backport #29612 (session-token budget-ceiling exemption) into stable/1.86.x and cut 1.86.5 - #29635

Merged
mateo-berri merged 4 commits into
stable/1.86.xfrom
litellm_cherrypick_1_86_5
Jun 4, 2026
Merged

chore(release): backport #29612 (session-token budget-ceiling exemption) into stable/1.86.x and cut 1.86.5#29635
mateo-berri merged 4 commits into
stable/1.86.xfrom
litellm_cherrypick_1_86_5

Conversation

@mateo-berri

@mateo-berri mateo-berri commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

Backports #29612 (fixes #29073) onto the 1.86.x line, which already received the earlier batch (#29628#29632). Cherry-picked from the squashed commit that landed on litellm_internal_staging (97ba7e1a30). Cuts 1.86.5

What is included

The last two commits are the version bump (1.86.4 → 1.86.5) and the matching uv.lock refresh

#29612 applies cleanly here: 1.86.x carries the GHSA-q775 delegated-authority budget ceiling (introduced by #27897) that this fix adds an exemption to. The cherry-pick is byte-identical to upstream (2 files changed, 93 insertions(+), no conflicts)

Note: this fix is intentionally NOT backported to 1.84.x or 1.85.x. Those lines predate the GHSA-q775 ceiling (#27897), so there is nothing to exempt — the bug #29612 fixes cannot occur there, and cherry-picking would insert code referencing an undefined _requested_max_budget

Pre-Submission checklist

  • The cherry-picked PR carries its own tests
  • My PR passes all unit tests on make test-unit
  • Scope is limited to backporting an already-merged fix plus the release bump

Type

Bug Fix
Infrastructure

Changes

See the commit list. No new code beyond the cherry-pick, the version bump, and the lockfile refresh

yuneng-berri and others added 3 commits June 3, 2026 23:45
…ng for team keys (#29612)

Non-admin users creating a team key through the UI were rejected with
"max_budget cannot exceed the caller's own max_budget (0.25)". The request is
authenticated by a UI/CLI session token whose max_budget is the per-session chat
spend cap (max_ui_session_budget, default $0.25), and the delegated-authority
budget ceiling (GHSA-q775-qw9r-2r4g) treated that cap as a delegation limit.

Skip the ceiling only when a session token creates a team key (data.team_id set);
that key's spend is bounded by the team budget at request time. Personal keys and
every other non-admin caller keep the ceiling, so a session token cannot mint an
arbitrary-budget personal key.

(cherry picked from commit 97ba7e1)
@mateo-berri
mateo-berri marked this pull request as ready for review June 4, 2026 00:09
@mateo-berri
mateo-berri requested review from a team and tin-berri June 4, 2026 00:09
@mateo-berri
mateo-berri enabled auto-merge June 4, 2026 00:09
@greptile-apps

greptile-apps Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This backport cherry-picks #29612 onto stable/1.86.x and cuts 1.86.5. The fix exempts UI/CLI session tokens from the GHSA-q775 delegated-authority budget ceiling when they are creating a team key — a use case the ceiling was never meant to block — while preserving the ceiling for personal-key creation where it is security-critical.

  • key_management_endpoints.py: captures _requested_team_id before the defaults loop, then adds is_ui_session_team_key (caller's team_id == UI_SESSION_TOKEN_TEAM_ID and the caller explicitly requested a team key) as a skip-ceiling guard.
  • Three regression tests cover the exemption path, the personal-key ceiling (expected to still fire), and a subtle default-injection bypass scenario.

Confidence Score: 5/5

Safe to merge — the change is a narrow, well-scoped exemption that preserves the budget ceiling for all personal-key creation paths and is guarded by three targeted regression tests.

The implementation correctly captures _requested_team_id before the defaults loop to prevent the config-injection bypass, and gates the exemption on both the caller being a UI session token and the caller explicitly supplying a team_id. The two security-regression tests (personal-key ceiling, defaults-injection) use strong assertions; they would catch any regression that weakened the ceiling. No logic errors or new attack surface introduced.

No files require special attention.

Important Files Changed

Filename Overview
litellm/proxy/management_endpoints/key_management_endpoints.py Captures _requested_team_id before the defaults loop and adds is_ui_session_team_key guard to exempt UI/CLI session tokens from the GHSA-q775 budget ceiling only when explicitly creating a team key. Logic is correct and well-commented.
tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py Adds three targeted regression tests. The two security-regression tests (personal key ceiling, default-team_id bypass) use strong pytest.raises assertions. The exemption test uses a weaker try/except pattern (already flagged in previous review thread).
pyproject.toml Routine version bump 1.86.4 → 1.86.5 in both [project] and [tool.commitizen] sections.

Reviews (2): Last reviewed commit: "fix(key_generate): harden GHSA-q775 sess..." | Re-trigger Greptile

Comment on lines +11491 to +11499

@pytest.mark.asyncio
async def test_ghsa_q775_ui_session_token_personal_key_still_capped():
"""
Security regression for GHSA-q775: the session-token exemption must NOT extend
to personal keys. A UI/CLI session token (team_id=litellm-dashboard) creating a
key with no data.team_id is still bound by the ceiling; otherwise a session
token - or a leaked one, whose blast radius is the $0.25 chat cap - could mint
an arbitrary-budget personal key, the exact escalation GHSA-q775 closed. Unlike

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Weak assertion may pass even if ceiling check is never reached

The try/except only asserts that the failure message (if any) does not contain "cannot exceed". If _common_key_generation_helper raises for a completely different reason before it reaches the budget-ceiling block (e.g., a mock attribute access error from team_table=MagicMock()), the assertion still passes, giving a false green on the exemption under test. Consider asserting an explicit success or using pytest.raises with a match on the opposite condition, similar to how the companion personal-key test uses pytest.raises(...) as exc_info followed by a strong assert "cannot exceed" in msg.lower().

@codecov

codecov Bot commented Jun 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...y/management_endpoints/key_management_endpoints.py 0.00% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@mateo-berri
mateo-berri disabled auto-merge June 4, 2026 01:03
…efault_key_generate_params

Capture _requested_team_id before the default_key_generate_params loop runs and
key the UI/CLI session-token budget-ceiling exemption off it, instead of the
post-defaults data.team_id. On an install that sets
default_key_generate_params.team_id, a session token requesting a personal key
(no explicit team_id) would otherwise have data.team_id auto-filled, flipping
is_ui_session_team_key on and bypassing the delegated-authority ceiling -- the
exact escalation GHSA-q775 closed. Mirrors the existing pre-defaults capture of
_requested_max_budget. Adds a regression test.

https://claude.ai/code/session_01RT583b1khYC3wjLrQ5hT5h
(cherry picked from commit efeb101)
@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

@mateo-berri
mateo-berri merged commit 1b31690 into stable/1.86.x Jun 4, 2026
89 of 102 checks passed
@mateo-berri
mateo-berri deleted the litellm_cherrypick_1_86_5 branch June 4, 2026 02:31
@mateo-berri
mateo-berri removed the request for review from tin-berri June 4, 2026 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants