fix(proxy): block POST /user/new during the master key lockout

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
mateo 2026-09-15 18:06:57 +00:00
parent cbe7857af2
commit a40804b7dc
2 changed files with 9 additions and 2 deletions

View file

@ -41,6 +41,8 @@ class _DeploymentMarker(TypedDict, total=False):
_DEPLOYMENT_MARKERS: Final = TypeAdapter(list[_DeploymentMarker])
_VIRTUAL_KEY_MINTING_ROUTES: Final = ("/user/new",)
_ACCESS_CREDENTIAL_ROUTES: Final = (
"/credentials",
"/credentials/by_name/{credential_name:path}",
@ -121,7 +123,7 @@ def request_http_method(request: Request) -> str:
method: Final = request.method
except (KeyError, AttributeError):
return ""
return method if isinstance(method, str) else ""
return method if isinstance(method, str) else "" # pyright: ignore[reportUnnecessaryIsInstance] # spec'd request mocks return a Mock, not a str
def master_key_lockout_action(
@ -140,7 +142,9 @@ def master_key_lockout_action(
return "access_credentials"
if method.upper() != "GET" and RouteChecks.is_llm_api_route(route=route):
return "use_credentials"
if method.upper() != "GET" and _route_matches_any(route, tuple(LiteLLMRoutes.key_management_routes.value)):
if method.upper() != "GET" and _route_matches_any(
route, tuple(LiteLLMRoutes.key_management_routes.value) + _VIRTUAL_KEY_MINTING_ROUTES
):
return "manage_virtual_keys"
return None

View file

@ -102,7 +102,9 @@ def test_insecure_master_key_warning_survives_redaction():
("/key/abc-def/regenerate", "POST", "manage_virtual_keys"),
("/key/service-account/generate", "POST", "manage_virtual_keys"),
("/key/block", "POST", "manage_virtual_keys"),
("/user/new", "POST", "manage_virtual_keys"),
("/key/info", "GET", None),
("/user/info", "GET", None),
("/key/list", "GET", None),
("/login", "POST", None),
("/health/readiness", "GET", None),
@ -140,6 +142,7 @@ def test_master_key_lockout_action_none_when_key_secure(route, method):
("/chat/completions", "POST"),
("/key/generate", "POST"),
("/key/abc/regenerate", "POST"),
("/user/new", "POST"),
],
)
@pytest.mark.parametrize("reason", ["example_key", "missing"])