mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
* fix(cli): mint per-session agent credential on lite login
The `lite login` command was producing a shared UI session token that broke agent use in three ways: a $0.25 budget cap (from max_ui_session_budget) that killed agent sessions in minutes, a fixed identity "cli-jwt-token" shared across every user preventing per-session spend attribution, and auth gated behind EXPERIMENTAL_UI_LOGIN so the token was rejected on default deployments.
This fixes all three. Each login now generates a unique cli-session-{uuid} token with no per-key budget cap (enforced via shared team/user counters instead), and the decrypt path activates for any non-sk- token without requiring EXPERIMENTAL_UI_LOGIN.
* fix(cli): address review feedback on EXPERIMENTAL_UI_LOGIN gate and e2e test
Restore EXPERIMENTAL_UI_LOGIN=false as an explicit opt-out: operators who set it to false keep the old boundary; unset (new default) and true both attempt NaCl decryption, which fails closed for non-blob tokens.
In the e2e test: replace the silent Redis fallback with pytest.skip so a missing Redis instance is explicit rather than silently degrading to a directly-minted token. Write the seeded flow back as JSON (proxy reads it via json.loads on cache fetch) instead of Python repr, and build the updated flow immutably.
* fix(key-management): cap CLI session token delegation budget to team ceiling
A CLI session token intentionally carries max_budget=None to avoid a per-session LLM spend cap. The key-generation delegation check (GHSA-q775-qw9r-2r4g) previously skipped non-admin callers with max_budget=None, treating them as having unlimited delegation authority. This allowed any internal user with a lite login session to mint virtual keys with arbitrary budgets.
Adds is_session_token=True to UserAPIKeyAuth for CLI session tokens and uses the caller's team budget as the delegation ceiling in that case, so the effective limit is min(requested_budget, team.max_budget) rather than unbounded.
* chore: regenerate dashboard OpenAPI types
The is_session_token field added to UserAPIKeyAuth cascades to the
dashboard schema. Regenerate types from the updated OpenAPI spec.
* fix(key-management): block personal key budget delegation from CLI session tokens
When team_table is None (personal key, no team_id in request), the personal key
has no team-budget enforcement at request time. A session token therefore cannot
delegate any explicit max_budget for a personal key -- that would open a budget
bypass path. Block the request with a clear 400 directing the caller to use a
team_id instead.
* test(auth): add unit coverage for non-admin CLI session token production path
* fix(type-check): use model_validate in _return_user_api_key_auth_obj to fix reportArgumentType gate
UserAPIKeyAuth(**user_api_key_kwargs) spread triggers a basedpyright
reportArgumentType error for each named field in UserAPIKeyAuth because
the dict's inferred value type (str | Span | LitellmUserRoles | Unknown)
is not assignable to each field's specific type. Adding is_session_token:
bool introduced +2 more such errors, breaching the gate cap.
model_validate accepts an untyped dict without per-field argument checking,
which eliminates the +2 new errors and also ratchets down the pre-existing
333 errors at those call sites. basedpyright-code-budget.json is updated
to reflect the new lower baseline (1814, down from 1934).
* fix(type-check): ratchet down reportArgumentType baseline only
The previous lint-budget-update captured all baselines from the local
environment, raising many ceilings vs the merge-base and failing the
non-gating budget_ratchet_check. Restore staging's values for every
rule and only lower reportArgumentType (1934 -> 1814) to reflect the
reduction from switching to model_validate in _return_user_api_key_auth_obj.
* fix(auth): set max_budget on CLI session token to enforce max_ui_session_budget
CLI session tokens were missing max_budget, so _virtual_key_max_budget_check
had no per-session ceiling to enforce. Operators relying on max_ui_session_budget
could be bypassed for the full token lifetime. Mirrors the existing UI token path.
* revert(auth): remove max_ui_session_budget from CLI session token
max_ui_session_budget defaults to $0.25 and is sized for the UI chat
pane (10-min sessions). CLI sessions are 24-hour tokens for real work;
capping them at that ceiling would throttle users under their actual
user/team budget. Budget enforcement for CLI sessions is via the shared
user and team counters as originally intended.
* fix(auth): cap CLI session at max_ui_session_budget only when user and team have no budget
When neither the user nor their team has a budget configured, CLI sessions
were fully uncapped. The poll endpoint now looks up the real user and team
objects from DB; if both have no max_budget, it passes litellm.max_ui_session_budget
as the token's per-key ceiling. Users or teams that already have a budget
configured are unaffected and continue to rely on the shared counters.
* fix(auth): fix black formatting and update test mock for cli_poll_key budget lookup
The get_user_object and get_team_object async calls in cli_poll_key were
not mocked in the existing test, causing MagicMock await errors. Patch
both functions at the auth_checks module level. Also apply black formatting
to ui_sso.py which CI rejected.
* fix(auth): skip fallback budget cap when team lookup fails for cli session token
* test(auth): pin cli session budget cap to user/team budget presence
The session_max_budget fallback in cli_poll_key only applied
max_ui_session_budget when neither the user nor the resolved team had a
budget. The existing coverage exercised only the team-lookup-failure
branch. Add two regression tests: a user with a configured budget must
not receive the fallback cap, and a session with no user and no team
budget must fall back to max_ui_session_budget. Mutating either guard
out of the branch now fails these tests.
* fix: remove CLI poll session budget cap
* revert(auth): restore CLI session fallback budget cap
Bugbot autofix (60b81fb8) removed the user/team budget lookup in
cli_poll_key and stopped passing max_budget to the session token,
making CLI sessions fully uncapped whenever neither the user nor the
team has an explicit budget.
That reintroduces the unbounded-spend bypass veria flagged as High
("CLI session budget bypass"): on deployments that rely on
max_ui_session_budget rather than per-user/team budgets, a completed
lite login could run LLM calls with no ceiling for the whole token
lifetime. The fallback only applies when no other budget bounds the
session, so users and teams with a configured budget are unaffected and
keep relying on their shared counters.
---------
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
194 lines
3.4 KiB
JSON
194 lines
3.4 KiB
JSON
{
|
|
"reportAny": {
|
|
"baseline": 24989,
|
|
"slack": 2500
|
|
},
|
|
"reportArgumentType": {
|
|
"baseline": 1814,
|
|
"slack": 180
|
|
},
|
|
"reportAssignmentType": {
|
|
"baseline": 220,
|
|
"slack": 22
|
|
},
|
|
"reportAttributeAccessIssue": {
|
|
"baseline": 346,
|
|
"slack": 35
|
|
},
|
|
"reportCallIssue": {
|
|
"baseline": 87,
|
|
"slack": 10
|
|
},
|
|
"reportConstantRedefinition": {
|
|
"baseline": 39,
|
|
"slack": 4
|
|
},
|
|
"reportDeprecated": {
|
|
"baseline": 217,
|
|
"slack": 22
|
|
},
|
|
"reportDuplicateImport": {
|
|
"baseline": 28,
|
|
"slack": 3
|
|
},
|
|
"reportExplicitAny": {
|
|
"baseline": 6931,
|
|
"slack": 700
|
|
},
|
|
"reportFunctionMemberAccess": {
|
|
"baseline": 7,
|
|
"slack": 3
|
|
},
|
|
"reportGeneralTypeIssues": {
|
|
"baseline": 151,
|
|
"slack": 15
|
|
},
|
|
"reportIncompatibleMethodOverride": {
|
|
"baseline": 52,
|
|
"slack": 5
|
|
},
|
|
"reportIncompatibleVariableOverride": {
|
|
"baseline": 8,
|
|
"slack": 3
|
|
},
|
|
"reportInconsistentOverload": {
|
|
"baseline": 12,
|
|
"slack": 3
|
|
},
|
|
"reportIndexIssue": {
|
|
"baseline": 26,
|
|
"slack": 3
|
|
},
|
|
"reportInvalidTypeForm": {
|
|
"baseline": 23,
|
|
"slack": 3
|
|
},
|
|
"reportInvalidTypeVarUse": {
|
|
"baseline": 2,
|
|
"slack": 3
|
|
},
|
|
"reportMatchNotExhaustive": {
|
|
"baseline": 1,
|
|
"slack": 0
|
|
},
|
|
"reportMissingParameterType": {
|
|
"baseline": 3933,
|
|
"slack": 390
|
|
},
|
|
"reportMissingTypeArgument": {
|
|
"baseline": 10612,
|
|
"slack": 1000
|
|
},
|
|
"reportMissingTypeStubs": {
|
|
"baseline": 27,
|
|
"slack": 10
|
|
},
|
|
"reportOperatorIssue": {
|
|
"baseline": 6,
|
|
"slack": 3
|
|
},
|
|
"reportOptionalCall": {
|
|
"baseline": 4,
|
|
"slack": 3
|
|
},
|
|
"reportOptionalIterable": {
|
|
"baseline": 3,
|
|
"slack": 3
|
|
},
|
|
"reportOptionalMemberAccess": {
|
|
"baseline": 724,
|
|
"slack": 72
|
|
},
|
|
"reportOptionalOperand": {
|
|
"baseline": 3,
|
|
"slack": 3
|
|
},
|
|
"reportOptionalSubscript": {
|
|
"baseline": 11,
|
|
"slack": 3
|
|
},
|
|
"reportPossiblyUnboundVariable": {
|
|
"baseline": 52,
|
|
"slack": 10
|
|
},
|
|
"reportPrivateUsage": {
|
|
"baseline": 1625,
|
|
"slack": 160
|
|
},
|
|
"reportRedeclaration": {
|
|
"baseline": 8,
|
|
"slack": 3
|
|
},
|
|
"reportReturnType": {
|
|
"baseline": 126,
|
|
"slack": 100
|
|
},
|
|
"reportTypedDictNotRequiredAccess": {
|
|
"baseline": 20,
|
|
"slack": 3
|
|
},
|
|
"reportUndefinedVariable": {
|
|
"baseline": 2,
|
|
"slack": 3
|
|
},
|
|
"reportUnknownArgumentType": {
|
|
"baseline": 30603,
|
|
"slack": 3000
|
|
},
|
|
"reportUnknownLambdaType": {
|
|
"baseline": 75,
|
|
"slack": 10
|
|
},
|
|
"reportUnknownMemberType": {
|
|
"baseline": 27037,
|
|
"slack": 2500
|
|
},
|
|
"reportUnknownParameterType": {
|
|
"baseline": 13612,
|
|
"slack": 1000
|
|
},
|
|
"reportUnknownVariableType": {
|
|
"baseline": 21445,
|
|
"slack": 2000
|
|
},
|
|
"reportUnnecessaryCast": {
|
|
"baseline": 118,
|
|
"slack": 10
|
|
},
|
|
"reportUnnecessaryComparison": {
|
|
"baseline": 683,
|
|
"slack": 100
|
|
},
|
|
"reportUnnecessaryContains": {
|
|
"baseline": 4,
|
|
"slack": 3
|
|
},
|
|
"reportUnnecessaryIsInstance": {
|
|
"baseline": 808,
|
|
"slack": 80
|
|
},
|
|
"reportUntypedBaseClass": {
|
|
"baseline": 110,
|
|
"slack": 11
|
|
},
|
|
"reportUntypedFunctionDecorator": {
|
|
"baseline": 22,
|
|
"slack": 3
|
|
},
|
|
"reportUnusedClass": {
|
|
"baseline": 22,
|
|
"slack": 3
|
|
},
|
|
"reportUnusedFunction": {
|
|
"baseline": 137,
|
|
"slack": 10
|
|
},
|
|
"reportUnusedImport": {
|
|
"baseline": 670,
|
|
"slack": 50
|
|
},
|
|
"reportUnusedVariable": {
|
|
"baseline": 865,
|
|
"slack": 50
|
|
}
|
|
}
|