Skip to content

fix(keys): use user-account budget as delegation ceiling for UI session personal keys - #33243

Open
devin-ai-integration[bot] wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_fix_ui_personal_key_max_budget_33212
Open

fix(keys): use user-account budget as delegation ceiling for UI session personal keys#33243
devin-ai-integration[bot] wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_fix_ui_personal_key_max_budget_33212

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Relevant issues

Fixes #33212

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Screenshots / Proof of Fix

Repro against a live proxy (no LLM calls needed; this is a key-creation budget gate). Log in to the UI as a non-admin internal user whose account max_budget is $100, then create a personal key (no team) with max_budget=4.

Before this change the request is rejected with max_budget (4.0) cannot exceed the caller's own max_budget (0.25), because the delegation ceiling was read from the UI session token's per-session chat cap (max_ui_session_budget, default $0.25) instead of the user account.

After this change the same request succeeds, and a request above the user's account budget (e.g. max_budget=500 for a $100 account) is still rejected with a message naming the $100 ceiling.

Type

🐛 Bug Fix

Changes

A non-admin user creating a personal virtual key through the UI was blocked by the delegated-authority ceiling (GHSA-q775-qw9r-2r4g). The UI authenticates with a session token whose team_id is litellm-dashboard and whose max_budget is max_ui_session_budget (default $0.25); that value is a per-session chat spend cap, not the caller's real authority, but _common_key_generation_helper read it directly as the ceiling:

delegation_ceiling = (
    user_api_key_dict.max_budget  # 0.25 for a UI session token
    if user_api_key_dict.max_budget is not None
    else ...
)

The team-key path was already exempted in #29612, but personal keys kept using the $0.25 cap, so any personal-key max_budget above $0.25 failed.

This adds _resolve_delegation_ceiling, which detects a UI session token (team_id == UI_SESSION_TOKEN_TEAM_ID) and resolves the ceiling from the caller's user-account budget via get_user_object rather than the session cap. If the user cannot be resolved it fails closed to the session cap, so a leaked session token still cannot mint an above-authority personal key. Every other caller keeps delegating from its own max_budget, falling back to the team budget for a CLI session token creating a team key, exactly as before.

Net effect: a UI user with a $100 account can create a personal key up to $100 (the reported case with max_budget=4 now works), while requests above the account budget stay rejected.

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Link to Devin session: https://app.devin.ai/sessions/451806c786fb4d76bdbb46e2c60d6c16

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where a non-admin user creating a personal virtual key via the UI was incorrectly blocked because the delegation-authority ceiling was read from the UI session token's per-session chat spend cap (max_ui_session_budget, default $0.25) rather than the caller's actual user-account budget.

  • Introduces _resolve_delegation_ceiling, which detects a UI session token (team_id == UI_SESSION_TOKEN_TEAM_ID) and resolves the ceiling from the caller's user-account record via get_user_object; all other callers are unaffected.
  • Fails closed to the session cap when the user account cannot be resolved, so a leaked token still cannot mint an above-authority key.
  • Adds three new tests: within-budget personal key now succeeds, above-account-budget key is still rejected with the correct ceiling, and the fail-closed path (unresolvable user) is also exercised.

Confidence Score: 4/5

Safe to merge; the new code path is narrowly scoped to UI session tokens and fails closed on every error path.

The _resolve_delegation_ceiling function correctly reads the user account budget from the cache/DB and handles the user_id=None, user-not-found, and prisma_client=None cases by falling back to the session cap. The modified test was legitimately updated to reflect the new correct ceiling, and coverage is extended rather than reduced. The only minor note is that every UI-session personal-key creation now issues a get_user_object call; this is mitigated by the existing cache layer in get_user_object and is not on the LLM request path.

No files require special attention beyond a quick sanity-check of _resolve_delegation_ceiling and the renamed security regression test.

Important Files Changed

Filename Overview
litellm/proxy/management_endpoints/key_management_endpoints.py Adds _resolve_delegation_ceiling to look up the caller's user-account budget when the token is a UI session token, rather than relying on the per-session chat cap; fails closed to the session cap if the user cannot be resolved.
tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py Renames and updates the personal-key ceiling security test to reflect the new user-account ceiling; adds two new tests covering the within-budget success path and the fail-closed behavior when the user cannot be resolved.

Reviews (1): Last reviewed commit: "fix(keys): use user-account budget as de..." | Re-trigger Greptile

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_fix_ui_personal_key_max_budget_33212 (70a16ed) with litellm_internal_staging (93b5ca9)

Open in CodSpeed

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.

[Bug]: Non-admin users cannot set max_budget on personal keys via UI

1 participant