Fix spend logs v2 route permissions (#28705)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: ryan-crabbe-berri <ryan-crabbe-berri@users.noreply.github.com>
This commit is contained in:
ryan-crabbe-berri 2026-05-23 16:57:14 -07:00 committed by GitHub
parent 92d4bba58f
commit 4148667671
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 0 deletions

View File

@ -255,6 +255,7 @@ class KeyManagementRoutes(str, enum.Enum):
# team spend-log viewing
SPEND_LOGS = "/spend/logs"
SPEND_LOGS_V2 = "/spend/logs/v2"
class LiteLLMRoutes(enum.Enum):
@ -548,6 +549,7 @@ class LiteLLMRoutes(enum.Enum):
KeyManagementRoutes.TEAM_KEY_BULK_UPDATE.value,
KeyManagementRoutes.TEAM_DAILY_ACTIVITY.value,
KeyManagementRoutes.SPEND_LOGS.value,
KeyManagementRoutes.SPEND_LOGS_V2.value,
KeyManagementRoutes.KEY_RESET_SPEND.value,
KeyManagementRoutes.KEY_ALIASES.value,
]
@ -599,6 +601,7 @@ class LiteLLMRoutes(enum.Enum):
"/spend/tags",
"/spend/calculate",
"/spend/logs",
"/spend/logs/v2",
"/spend/logs/ui",
"/spend/logs/session/ui",
"/cost/estimate",

View File

@ -268,6 +268,47 @@ def test_mcp_management_routes_classified_as_management_not_llm_api(route):
assert RouteChecks.is_management_route(route=route) is True
def test_spend_logs_v2_classified_as_management_not_llm_api():
"""Paginated spend logs are a management/spend read route, not an LLM API."""
assert RouteChecks.is_llm_api_route(route="/spend/logs/v2") is False
assert RouteChecks.is_management_route(route="/spend/logs/v2") is True
def test_virtual_key_management_routes_allows_spend_logs_v2():
"""Management virtual keys should be allowed to call the v2 spend logs endpoint."""
valid_token = UserAPIKeyAuth(
user_id="test_user",
allowed_routes=["management_routes"],
)
result = RouteChecks.is_virtual_key_allowed_to_call_route(
route="/spend/logs/v2",
valid_token=valid_token,
)
assert result is True
def test_virtual_key_llm_api_routes_denies_spend_logs_v2():
"""AI API virtual keys should not gain spend-log access."""
valid_token = UserAPIKeyAuth(
user_id="test_user",
allowed_routes=["llm_api_routes"],
)
with pytest.raises(HTTPException) as exc_info:
RouteChecks.is_virtual_key_allowed_to_call_route(
route="/spend/logs/v2",
valid_token=valid_token,
)
assert exc_info.value.status_code == 403
assert "Virtual key is not allowed to call this route" in str(exc_info.value.detail)
@pytest.mark.parametrize(
"route",
[
@ -1322,6 +1363,7 @@ ADMIN_VIEWER_LOGS_PAGE_ROUTES = [
"/cost/estimate",
# Public spend logs / spend tracking routes that admin viewer should read
"/spend/logs",
"/spend/logs/v2",
"/spend/keys",
"/spend/users",
"/spend/tags",