Skip to content

[Fix] Allow non-admin compliance path reads - #27234

Merged
Michael-RZ-Berri merged 2 commits into
litellm_internal_stagingfrom
litellm_adminAuthLogNoise
May 7, 2026
Merged

[Fix] Allow non-admin compliance path reads#27234
Michael-RZ-Berri merged 2 commits into
litellm_internal_stagingfrom
litellm_adminAuthLogNoise

Conversation

@Michael-RZ-Berri

@Michael-RZ-Berri Michael-RZ-Berri commented May 5, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

The logs page logs an error every 15 seconds that a non-admin user stays on the page and has a row-information side panel open. This is because compliance, for relevant requests, was gated to only be viewable to admins on the backend, even though compliance is included in the request information for every user when present. This PR allows internal users to see compliance so there aren't a flood of errors because a page was left open.

Linear ticket

Resolves LIT-2760.

Pre-Submission checklist

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

  • I have Added testing in the tests/test_litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

Screenshots / Proof of Fix

Screenshot 2026-05-05 at 2 31 15 PM

Type

🐛 Bug Fix
✅ Test

Changes

_types file


Note

Medium Risk
Touches RBAC route allowlists; mistakes could unintentionally broaden access, though the change is narrowly scoped to two stateless compliance endpoints and covered by tests.

Overview
Allows non-admin internal_user callers to access the compliance validation endpoints (/compliance/eu-ai-act, /compliance/gdpr) by adding them to LiteLLMRoutes.internal_user_routes.

Adds route-check tests to ensure these endpoints are permitted for INTERNAL_USER and still denied for the deprecated INTERNAL_USER_VIEW_ONLY role.

Reviewed by Cursor Bugbot for commit 46f5554. Bugbot is set up for automated code reviews on this repo. Configure here.

@CLAassistant

CLAassistant commented May 5, 2026

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 all sign our Contributor License Agreement before we can accept your contribution.
0 out of 2 committers have signed the CLA.

❌ Michael Riad Zaky
❌ cursoragent


Michael Riad Zaky seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps

greptile-apps Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a repeated 15-second error on the logs page by allowing internal_user callers to reach the stateless compliance validation endpoints (/compliance/eu-ai-act, /compliance/gdpr). The endpoints accept caller-supplied log data and perform no database lookups, so widening access to this role does not expose cross-tenant data.

  • Introduces a compliance_check_routes list in LiteLLMRoutes and appends it to internal_user_routes; internal_user_view_only_routes is deliberately left unchanged.
  • Adds two parametrized tests verifying that INTERNAL_USER is permitted and INTERNAL_USER_VIEW_ONLY remains blocked.

Confidence Score: 5/5

Safe to merge — the access change is narrow, the endpoints are stateless validators on caller-supplied data, and the role boundary for view-only users is preserved.

The compliance endpoints take a ComplianceCheckRequest payload and run purely in-process checks with no database access or cross-tenant data retrieval, so granting internal_user access does not widen the data surface. The existing route-allowlist pattern is followed exactly, and both the positive and negative access cases are covered by new tests.

No files require special attention.

Important Files Changed

Filename Overview
litellm/proxy/_types.py Adds compliance_check_routes list and appends it to internal_user_routes; internal_user_view_only_routes is intentionally unchanged, preserving the access boundary for that role.
tests/test_litellm/proxy/auth/test_route_checks.py Adds two parametrized tests: one confirming INTERNAL_USER can reach the compliance routes, one confirming INTERNAL_USER_VIEW_ONLY is still blocked with the expected exception message.

Reviews (3): Last reviewed commit: "Restrict compliance routes to internal u..." | Re-trigger Greptile

@codecov

codecov Bot commented May 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@oss-pr-review-agent-shin

Copy link
Copy Markdown
Contributor

🤖 litellm-agent: Merged into staging branch litellm_agent_oss_staging_05_06_2026. Staging PR: #27256


Triage Summary
Adds two compliance check routes (/compliance/eu-ai-act and /compliance/gdpr) to the LiteLLMRoutes enum and makes them accessible to non-admin internal_user roles (both INTERNAL_USER and INTERNAL_USER_VIEW_ONLY). The rationale in the code comment is that these endpoints are stateless validators on caller-supplied log data, so granting access does not expand the caller's data scope. A parametrized pytest is added to confirm both routes pass the non_proxy_admin_allowed_routes_check for both roles.

Merge Confidence: 5/5 ✅ READY
Ready to ship.

All checks green. Greptile 5/5, no blocking pattern findings, CircleCI passed.

@krrish-berri-2

Copy link
Copy Markdown
Contributor

This PR is wrong. the pr changes the available routes for view only users. @Michael-RZ-Berri do you mean internal_users or internal users with view only role?

those are 2 separate roles. internal_user_viewer is deprecated - https://docs.litellm.ai/docs/proxy/access_control#internal-user-viewer---read-only-access

@krrish-berri-2 krrish-berri-2 reopened this May 6, 2026

@cursor cursor Bot left a comment

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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Route expansion applied to deprecated view-only role
    • Removed compliance routes from the deprecated internal_user_viewer whitelist and updated route-check tests to assert only internal_user can access them.
Preview (9355564a16)
diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py
--- a/litellm/proxy/_types.py
+++ b/litellm/proxy/_types.py
@@ -656,6 +656,13 @@
         "/health/services",
     ] + info_routes
 
+    # Stateless validators on caller-supplied log data; source logs are
+    # already accessible via spend_tracking_routes, so no scope expansion.
+    compliance_check_routes = [
+        "/compliance/eu-ai-act",
+        "/compliance/gdpr",
+    ]
+
     # Routes in `global_spend_tracking_routes` return proxy-wide spend across
     # every team, customer, and api_key. They are intentionally NOT included
     # here — non-admin roles must not see other tenants' spend. Admin roles go
@@ -675,6 +682,7 @@
         ]
         + spend_tracking_routes
         + key_management_routes
+        + compliance_check_routes
     )
 
     internal_user_view_only_routes = spend_tracking_routes

diff --git a/tests/test_litellm/proxy/auth/test_route_checks.py b/tests/test_litellm/proxy/auth/test_route_checks.py
--- a/tests/test_litellm/proxy/auth/test_route_checks.py
+++ b/tests/test_litellm/proxy/auth/test_route_checks.py
@@ -53,6 +53,60 @@
     assert "Your role=internal_user" in str(exc_info.value)
 
 
+@pytest.mark.parametrize(
+    "route",
+    ["/compliance/eu-ai-act", "/compliance/gdpr"],
+)
+def test_compliance_routes_open_to_internal_user(route):
+    """Compliance routes are stateless validators on caller-supplied log data
+    - non-admin internal_user roles can call them."""
+    role = LitellmUserRoles.INTERNAL_USER.value
+    user_obj = LiteLLM_UserTable(
+        user_id="test_user",
+        user_email="test@example.com",
+        user_role=role,
+    )
+    valid_token = UserAPIKeyAuth(user_id="test_user", user_role=role)
+    request = MagicMock(spec=Request)
+    request.query_params = {}
+
+    RouteChecks.non_proxy_admin_allowed_routes_check(
+        user_obj=user_obj,
+        _user_role=role,
+        route=route,
+        request=request,
+        valid_token=valid_token,
+        request_data={},
+    )
+
+
+@pytest.mark.parametrize(
+    "route",
+    ["/compliance/eu-ai-act", "/compliance/gdpr"],
+)
+def test_compliance_routes_blocked_for_internal_user_view_only(route):
+    """Deprecated internal_user_viewer role must not gain compliance route access."""
+    role = LitellmUserRoles.INTERNAL_USER_VIEW_ONLY.value
+    user_obj = LiteLLM_UserTable(
+        user_id="test_user",
+        user_email="test@example.com",
+        user_role=role,
+    )
+    valid_token = UserAPIKeyAuth(user_id="test_user", user_role=role)
+    request = MagicMock(spec=Request)
+    request.query_params = {}
+
+    with pytest.raises(HTTPException):
+        RouteChecks.non_proxy_admin_allowed_routes_check(
+            user_obj=user_obj,
+            _user_role=role,
+            route=route,
+            request=request,
+            valid_token=valid_token,
+            request_data={},
+        )
+
+
 def test_proxy_admin_viewer_config_update_route_rejected():
     """Test that proxy admin viewer users are rejected when trying to call /config/update"""

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 2993e45. Configure here.

Comment thread litellm/proxy/_types.py Outdated
@oss-pr-review-agent-shin

Copy link
Copy Markdown
Contributor

🤖 litellm-agent: Reverted from staging branch litellm_agent_oss_staging_05_05_2026. PR reopened for re-review.

@Michael-RZ-Berri

Copy link
Copy Markdown
Contributor Author

This PR is wrong. the pr changes the available routes for view only users. @Michael-RZ-Berri do you mean internal_users or internal users with view only role?

those are 2 separate roles. internal_user_viewer is deprecated - https://docs.litellm.ai/docs/proxy/access_control#internal-user-viewer---read-only-access

Oh yeah didn't know they were deprecated, should be for internal_users only then.

@Michael-RZ-Berri
Michael-RZ-Berri force-pushed the litellm_adminAuthLogNoise branch from 9355564 to 6c0a4ad Compare May 6, 2026 23:24
@yuneng-berri

Copy link
Copy Markdown
Contributor

@greptile

@Michael-RZ-Berri
Michael-RZ-Berri force-pushed the litellm_adminAuthLogNoise branch from 6c0a4ad to 46f5554 Compare May 7, 2026 16:57
@Michael-RZ-Berri
Michael-RZ-Berri merged commit db8198f into litellm_internal_staging May 7, 2026
114 of 115 checks passed
@Michael-RZ-Berri
Michael-RZ-Berri deleted the litellm_adminAuthLogNoise branch May 7, 2026 19:07
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
* allow non-admin roles on /compliance/* read routes

* Restrict compliance routes to internal users

---------

Co-authored-by: Michael Riad Zaky <michaelr@Mac.localdomain>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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.

5 participants