feat(proxy): warn at startup when no master key is configured

This commit is contained in:
mateo 2026-09-11 22:47:21 +00:00 committed by Devin AI
parent 2f4032a984
commit d729121a14
4 changed files with 61 additions and 18 deletions

View file

@ -3,13 +3,20 @@ from typing import Final
INSECURE_MASTER_KEYS: Final = frozenset({"sk-1234"})
def insecure_master_key_warning(master_key: str | None) -> str | None:
if master_key not in INSECURE_MASTER_KEYS:
return None
return (
"LITELLM_MASTER_KEY is set to the example key 'sk-1234' from the docs. "
"Anyone who has read the docs can administer this gateway, and publicly reachable "
"gateways using this key have been compromised. Set a strong random master key "
"(e.g. `python -c \"import secrets; print('sk-' + secrets.token_urlsafe(32))\"`). "
"A future release will refuse to start with this key."
)
def insecure_master_key_warning(master_key: str | None, alternative_auth_enabled: bool) -> str | None:
if master_key in INSECURE_MASTER_KEYS:
return (
"LITELLM_MASTER_KEY is set to the example key 'sk-1234' from the docs. "
"Anyone who has read the docs can administer this gateway, and publicly reachable "
"gateways using this key have been compromised. Set a strong random master key "
"(e.g. `python -c \"import secrets; print('sk-' + secrets.token_urlsafe(32))\"`). "
"A future release will refuse to start with this key."
)
if (master_key is None or master_key == "") and not alternative_auth_enabled:
return (
"No master key is set (LITELLM_MASTER_KEY or general_settings.master_key). "
"Every request to this proxy is accepted without authentication, including "
'admin routes. Set a strong random master key (e.g. `python -c "import secrets; '
"print('sk-' + secrets.token_urlsafe(32))\"`) before exposing it to a network."
)
return None

View file

@ -1160,7 +1160,12 @@ async def proxy_startup_event(app: FastAPI) -> AsyncGenerator[None, None]:
if isinstance(worker_config, dict):
await initialize(**worker_config)
_insecure_master_key_warning: Final = insecure_master_key_warning(master_key)
_alternative_auth_enabled: Final = any(
general_settings.get(k, False) for k in ("enable_jwt_auth", "enable_oauth2_auth", "enable_oauth2_proxy_auth")
)
_insecure_master_key_warning: Final = insecure_master_key_warning(
master_key, alternative_auth_enabled=_alternative_auth_enabled
)
if _insecure_master_key_warning is not None:
verbose_proxy_logger.warning(_insecure_master_key_warning)

View file

@ -3,22 +3,36 @@ from litellm.proxy.auth.master_key_policy import insecure_master_key_warning
def test_insecure_master_key_warning_returned_for_example_key():
warning = insecure_master_key_warning("sk-1234")
warning = insecure_master_key_warning("sk-1234", alternative_auth_enabled=False)
assert warning is not None
assert "sk-1234" in warning
def test_insecure_master_key_warning_for_missing_key():
warning = insecure_master_key_warning(None, alternative_auth_enabled=False)
assert warning is not None
assert "No master key" in warning
def test_insecure_master_key_warning_for_empty_key():
warning = insecure_master_key_warning("", alternative_auth_enabled=False)
assert warning is not None
assert "No master key" in warning
def test_insecure_master_key_warning_none_for_missing_key_with_alt_auth():
assert insecure_master_key_warning(None, alternative_auth_enabled=True) is None
def test_insecure_master_key_warning_none_for_strong_key():
assert insecure_master_key_warning("sk-strong-random-key") is None
def test_insecure_master_key_warning_none_for_none():
assert insecure_master_key_warning(None) is None
assert insecure_master_key_warning("sk-strong-random-key", alternative_auth_enabled=False) is None
def test_insecure_master_key_warning_survives_redaction():
warning = insecure_master_key_warning("sk-1234")
warning = insecure_master_key_warning("sk-1234", alternative_auth_enabled=False)
assert warning is not None
assert "secrets.token_urlsafe" in redact_string(warning)

View file

@ -1090,3 +1090,20 @@ async def test_proxy_startup_event_warns_but_does_not_raise_for_docs_example_mas
pass
assert "sk-1234" in caplog.text, "startup should log the insecure master key warning"
@pytest.mark.asyncio
async def test_proxy_startup_event_warns_but_does_not_raise_for_missing_master_key(monkeypatch, caplog):
monkeypatch.delenv("LITELLM_MASTER_KEY", raising=False)
try:
with caplog.at_level(logging.WARNING, logger="LiteLLM Proxy"):
async with proxy_startup_event(app=None):
pass
except ValueError as e:
if "master key" in str(e).lower():
pytest.fail("proxy_startup_event refused to boot without a master key")
except Exception:
pass
assert "No master key" in caplog.text, "startup should log the missing master key warning"