From d78752b85b1a843318a03029b1ae05031622e23e Mon Sep 17 00:00:00 2001 From: Harshit28j Date: Sat, 7 Mar 2026 12:32:21 +0530 Subject: [PATCH 1/3] feat: feature flag on validate key alias --- litellm/__init__.py | 3 +++ .../key_management_endpoints.py | 10 +++++++-- .../test_key_management_endpoints.py | 21 +++++++++++++++++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/litellm/__init__.py b/litellm/__init__.py index d75f47567a..4fc71e1270 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -305,6 +305,9 @@ return_response_headers: bool = ( False # get response headers from LLM Api providers - example x-remaining-requests, ) enable_json_schema_validation: bool = False +enable_key_alias_format_validation: bool = ( + False # opt-in validation of key_alias format on /key/generate and /key/update +) #################### logging: bool = True enable_loadbalancing_on_batch_endpoints: Optional[bool] = None diff --git a/litellm/proxy/management_endpoints/key_management_endpoints.py b/litellm/proxy/management_endpoints/key_management_endpoints.py index 072d4181c6..3b54a79a73 100644 --- a/litellm/proxy/management_endpoints/key_management_endpoints.py +++ b/litellm/proxy/management_endpoints/key_management_endpoints.py @@ -5041,12 +5041,18 @@ def _validate_key_alias_format(key_alias: Optional[str]) -> None: """ Validate the format of the key_alias. - Rules: + Gated behind ``litellm.enable_key_alias_format_validation`` (default **False**). + When disabled, no validation is performed so existing workflows are not broken. + + Rules (when enabled): - None is OK (no alias). - Otherwise must be 2–255 chars - start/end with alphanumeric - - only allow a-zA-Z0-9_-/. + - only allow a-zA-Z0-9_-/.@ """ + if not litellm.enable_key_alias_format_validation: + return + if key_alias is None: return diff --git a/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py index 2533f0d66d..dc79322d57 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py @@ -2,6 +2,7 @@ import json import os import sys +import litellm import pytest import yaml from fastapi.testclient import TestClient @@ -6672,8 +6673,21 @@ async def test_key_aliases_admin_sees_all(): class TestValidateKeyAliasFormat: + def test_validation_skipped_when_flag_disabled(self): + """When enable_key_alias_format_validation is False (default), no validation occurs.""" + from litellm.proxy.management_endpoints.key_management_endpoints import _validate_key_alias_format + + litellm.enable_key_alias_format_validation = False + # Even invalid aliases should pass silently when the flag is off + _validate_key_alias_format(None) + _validate_key_alias_format("") + _validate_key_alias_format("!invalid!") + _validate_key_alias_format("a" * 256) + def test_validate_key_alias_format_valid(self): from litellm.proxy.management_endpoints.key_management_endpoints import _validate_key_alias_format + + litellm.enable_key_alias_format_validation = True # Valid cases _validate_key_alias_format(None) # OK _validate_key_alias_format("valid-alias") @@ -6684,11 +6698,13 @@ class TestValidateKeyAliasFormat: _validate_key_alias_format("my-key-123") _validate_key_alias_format("user/user@example.com") _validate_key_alias_format("team/user@example.com") + litellm.enable_key_alias_format_validation = False def test_validate_key_alias_format_invalid(self): from litellm.proxy.management_endpoints.key_management_endpoints import _validate_key_alias_format from litellm.proxy._types import ProxyException - + + litellm.enable_key_alias_format_validation = True invalid_aliases = [ "", # empty " ", # whitespace @@ -6701,9 +6717,10 @@ class TestValidateKeyAliasFormat: " leading", "trailing ", ] - + for alias in invalid_aliases: with pytest.raises(ProxyException) as exc: _validate_key_alias_format(alias) assert str(exc.value.code) == "400" assert "Invalid key_alias format" in str(exc.value.message) + litellm.enable_key_alias_format_validation = False From e33b26a45a4adaab59601682289945fbca436c51 Mon Sep 17 00:00:00 2001 From: Harshit28j Date: Sat, 7 Mar 2026 12:42:04 +0530 Subject: [PATCH 2/3] doc: add about flag feature --- docs/my-website/docs/proxy/config_settings.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/my-website/docs/proxy/config_settings.md b/docs/my-website/docs/proxy/config_settings.md index 23c0b1498f..bfaa2776fa 100644 --- a/docs/my-website/docs/proxy/config_settings.md +++ b/docs/my-website/docs/proxy/config_settings.md @@ -199,6 +199,7 @@ router_settings: | use_chat_completions_url_for_anthropic_messages | boolean | If true, routes OpenAI `/v1/messages` requests through chat/completions instead of the Responses API. Can also be set via env var `LITELLM_USE_CHAT_COMPLETIONS_URL_FOR_ANTHROPIC_MESSAGES=true`. | | disable_hf_tokenizer_download | boolean | If true, it defaults to using the openai tokenizer for all models (including huggingface models). | | enable_json_schema_validation | boolean | If true, enables json schema validation for all requests. | +| enable_key_alias_format_validation | boolean | If true, validates `key_alias` format on `/key/generate` and `/key/update`. Must be 2-255 chars, start/end with alphanumeric, only allow `a-zA-Z0-9_-/.@`. Default `false`. | | disable_copilot_system_to_assistant | boolean | **DEPRECATED** - GitHub Copilot API supports system prompts. | ### general_settings - Reference From 1452237ec61b95ba3891ff7fa3bcf48b39aae97b Mon Sep 17 00:00:00 2001 From: Harshit28j Date: Sat, 7 Mar 2026 12:45:49 +0530 Subject: [PATCH 3/3] fix req changes --- .../test_key_management_endpoints.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py index dc79322d57..6195f34f28 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_key_management_endpoints.py @@ -6673,11 +6673,16 @@ async def test_key_aliases_admin_sees_all(): class TestValidateKeyAliasFormat: + @pytest.fixture(autouse=True) + def reset_key_alias_flag(self): + litellm.enable_key_alias_format_validation = False + yield + litellm.enable_key_alias_format_validation = False + def test_validation_skipped_when_flag_disabled(self): """When enable_key_alias_format_validation is False (default), no validation occurs.""" from litellm.proxy.management_endpoints.key_management_endpoints import _validate_key_alias_format - litellm.enable_key_alias_format_validation = False # Even invalid aliases should pass silently when the flag is off _validate_key_alias_format(None) _validate_key_alias_format("") @@ -6698,7 +6703,6 @@ class TestValidateKeyAliasFormat: _validate_key_alias_format("my-key-123") _validate_key_alias_format("user/user@example.com") _validate_key_alias_format("team/user@example.com") - litellm.enable_key_alias_format_validation = False def test_validate_key_alias_format_invalid(self): from litellm.proxy.management_endpoints.key_management_endpoints import _validate_key_alias_format @@ -6723,4 +6727,3 @@ class TestValidateKeyAliasFormat: _validate_key_alias_format(alias) assert str(exc.value.code) == "400" assert "Invalid key_alias format" in str(exc.value.message) - litellm.enable_key_alias_format_validation = False