Skip to content

fix: align DefaultInternalUserParams Pydantic default with runtime fallback #23666

Merged
ryan-crabbe merged 3 commits intolitellm_ryan_march_16from
litellm_fix-default-user-perms-not-synced-with-ui
Mar 16, 2026
Merged

fix: align DefaultInternalUserParams Pydantic default with runtime fallback #23666
ryan-crabbe merged 3 commits intolitellm_ryan_march_16from
litellm_fix-default-user-perms-not-synced-with-ui

Conversation

@ryan-crabbe
Copy link
Copy Markdown
Contributor

Type

🐛 Bug Fix

Changes

The Pydantic default for user_role was INTERNAL_USER, but all runtime provisioning paths (SSO, SCIM, JWT) fall back to INTERNAL_USER_VIEW_ONLY when no settings are saved. This caused the UI to show "Internal User" on fresh instances while new users actually got "Internal Viewer".

Changed the default to be INTERNAL_USER_VIEW_ONLY to match what we have and be consistent.

…llback

The Pydantic default for user_role was INTERNAL_USER, but all runtime
provisioning paths (SSO, SCIM, JWT) fall back to INTERNAL_USER_VIEW_ONLY
when no settings are saved. This caused the UI to show "Internal User"
on fresh instances while new users actually got "Internal Viewer".
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Mar 14, 2026 10:43pm

Request Review

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 14, 2026

Greptile Summary

This PR fixes a mismatch between the Pydantic default value of user_role in DefaultInternalUserParams (INTERNAL_USER) and the runtime fallback used by SSO/SCIM/JWT provisioning paths (INTERNAL_USER_VIEW_ONLY), which caused the UI to display "Internal User" on fresh instances while new users were actually being granted "Internal Viewer" access.

Key changes:

  • litellm/proxy/_types.py: Changes the DefaultInternalUserParams.user_role default from LitellmUserRoles.INTERNAL_USER to LitellmUserRoles.INTERNAL_USER_VIEW_ONLY.
  • tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py: Adds test_get_internal_user_settings_fresh_db_defaults_to_viewer, an integration test that validates the /get/internal_user_settings endpoint returns INTERNAL_USER_VIEW_ONLY when no default_internal_user_params is saved in the config.

Concern: The DefaultInternalUserParams docstring explicitly states it also controls users created via the /user/new API endpoint — not just SSO. Changing the Pydantic default is therefore a global behavior change, not just a UI display fix. Deployments that relied on the previous default (no explicit config, users created via /user/new) will receive INTERNAL_USER_VIEW_ONLY instead of INTERNAL_USER after upgrading, with no opt-out mechanism. Per the project's backwards-compatibility policy, this warrants either a user-controlled flag or a migration notice.

Confidence Score: 3/5

  • Safe for fresh deployments, but could silently reduce permissions for existing deployments using /user/new without explicit default_internal_user_params config.
  • The one-line fix is correct and the new test validates the targeted scenario. However, the change affects more than just the UI display — it alters the effective default for any code path that instantiates DefaultInternalUserParams() without a saved config, including the /user/new API endpoint. This is a privilege reduction with no backwards-compatible fallback, which the project's policy flags as requiring a user-controlled flag or migration path.
  • Pay attention to litellm/proxy/_types.py — the default change applies globally, not just to the UI endpoint.

Important Files Changed

Filename Overview
litellm/proxy/_types.py Single-line change: default for DefaultInternalUserParams.user_role changed from INTERNAL_USER to INTERNAL_USER_VIEW_ONLY to align the Pydantic default with the runtime fallback used in SSO/SCIM/JWT provisioning paths.
tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py New integration test test_get_internal_user_settings_fresh_db_defaults_to_viewer added to verify the fresh-DB (no config) scenario returns INTERNAL_USER_VIEW_ONLY from the GET endpoint — directly covering the scenario fixed by this PR.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[New User Created] --> B{How?}
    B -->|SSO / SCIM / JWT| C[Runtime fallback logic]
    B -->|/user/new API| D[DefaultInternalUserParams default]
    B -->|UI GET /get/internal_user_settings| E[DefaultInternalUserParams default]

    C --> F{Config saved?}
    F -->|Yes| G[Use saved user_role]
    F -->|No| H[INTERNAL_USER_VIEW_ONLY]

    D --> I{Config saved?}
    I -->|Yes| J[Use saved user_role]
    I -->|No| K["BEFORE: INTERNAL_USER (was wrong)\nAFTER: INTERNAL_USER_VIEW_ONLY (now aligned)"]

    E --> L{Config saved?}
    L -->|Yes| M[Return saved user_role]
    L -->|No| N["BEFORE: INTERNAL_USER (displayed wrong)\nAFTER: INTERNAL_USER_VIEW_ONLY (now correct)"]

    style K fill:#f9a,stroke:#f00
    style N fill:#afa,stroke:#0a0
Loading

Last reviewed commit: c95783e

Asserts that GET /get/internal_user_settings returns
INTERNAL_USER_VIEW_ONLY on a fresh DB with no saved settings,
matching the runtime fallback in SSO/SCIM/JWT provisioning.
…endpoints.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@ryan-crabbe ryan-crabbe changed the base branch from main to litellm_ryan_march_16 March 16, 2026 18:55
@ryan-crabbe ryan-crabbe merged commit 4f2fe33 into litellm_ryan_march_16 Mar 16, 2026
91 of 97 checks passed
@ishaan-berri ishaan-berri deleted the litellm_fix-default-user-perms-not-synced-with-ui branch March 26, 2026 22:29
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.

1 participant