feat(ui): gate "Default Credentials" hint on /ui/login behind env flag (#30234)

Adds LITELLM_HIDE_DEFAULT_CREDENTIALS_HINT (and an equivalent
general_settings.hide_default_credentials_hint) that suppresses the
"By default, Username is admin and Password is your set LiteLLM Proxy
MASTER_KEY" info card rendered on /ui/login and /fallback/login.

Motivation: in production deployments operators set UI_USERNAME /
UI_PASSWORD (or SSO), and the hardcoded hint becomes factually
incorrect and is flagged by security scanners (Tenable WAS plugin
114625) as information disclosure. There is currently no way to
suppress it without forking the dashboard.

Behaviour:
- Default is unchanged (hint shown), so existing deployments are
  unaffected.
- New field hide_default_credentials_hint on the well-known UI config
  endpoint, populated from the env var or general_settings.
- LoginPage.tsx conditionally renders the Alert based on the flag.

Refs: BerriAI/litellm#30232
This commit is contained in:
apshada 2026-06-16 16:11:02 +05:30 • committed by GitHub
parent fc9d789d24
commit b11e59f3a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 104 additions and 22 deletions

View file

@ -25,6 +25,10 @@ async def get_ui_config():
or general_settings.get("auto_redirect_ui_login_to_sso", False) is True
)
admin_ui_disabled = os.getenv("DISABLE_ADMIN_UI", "false").lower() == "true"
hide_default_credentials_hint = (
os.getenv("LITELLM_HIDE_DEFAULT_CREDENTIALS_HINT", "false").lower() == "true"
or general_settings.get("hide_default_credentials_hint", False) is True
)
sso_configured = _has_user_setup_sso()
@ -38,6 +42,7 @@ async def get_ui_config():
auto_redirect_to_sso=sso_configured and auto_redirect_ui_login_to_sso,
admin_ui_disabled=admin_ui_disabled,
sso_configured=sso_configured,
hide_default_credentials_hint=hide_default_credentials_hint,
is_control_plane=is_control_plane,
workers=proxy_config.worker_registry if is_control_plane else [],
)

View file

@ -11,5 +11,6 @@ class UiDiscoveryEndpoints(BaseModel):
auto_redirect_to_sso: bool
admin_ui_disabled: bool
sso_configured: bool
hide_default_credentials_hint: bool = False
is_control_plane: bool = False
workers: List[WorkerRegistryEntry] = []

View file

@ -352,6 +352,79 @@ def test_ui_discovery_endpoints_is_control_plane_true_when_workers_configured():
assert data["workers"][0]["url"] == "https://worker-1:4001"
def test_ui_discovery_endpoints_hide_default_credentials_hint_default_false():
"""Default credentials hint is shown by default (flag false)."""
app = FastAPI()
app.include_router(router)
client = TestClient(app)
with (
patch("litellm.proxy.utils.get_server_root_path", return_value="/"),
patch("litellm.proxy.utils.get_proxy_base_url", return_value=None),
patch("litellm.proxy.auth.auth_utils._has_user_setup_sso", return_value=False),
patch.dict(os.environ, {"DISABLE_ADMIN_UI": "false"}, clear=False),
):
os.environ.pop("LITELLM_HIDE_DEFAULT_CREDENTIALS_HINT", None)
response = client.get("/.well-known/litellm-ui-config")
assert response.status_code == 200
data = response.json()
assert data["hide_default_credentials_hint"] is False
def test_ui_discovery_endpoints_hide_default_credentials_hint_via_env_var():
"""LITELLM_HIDE_DEFAULT_CREDENTIALS_HINT=true hides the login-page credentials card."""
app = FastAPI()
app.include_router(router)
client = TestClient(app)
with (
patch("litellm.proxy.utils.get_server_root_path", return_value="/"),
patch("litellm.proxy.utils.get_proxy_base_url", return_value=None),
patch("litellm.proxy.auth.auth_utils._has_user_setup_sso", return_value=False),
patch.dict(
os.environ,
{
"LITELLM_HIDE_DEFAULT_CREDENTIALS_HINT": "true",
"DISABLE_ADMIN_UI": "false",
},
clear=False,
),
):
response = client.get("/.well-known/litellm-ui-config")
assert response.status_code == 200
data = response.json()
assert data["hide_default_credentials_hint"] is True
def test_ui_discovery_endpoints_hide_default_credentials_hint_via_general_settings():
"""general_settings.hide_default_credentials_hint=true also hides the card."""
app = FastAPI()
app.include_router(router)
client = TestClient(app)
with (
patch("litellm.proxy.utils.get_server_root_path", return_value="/"),
patch("litellm.proxy.utils.get_proxy_base_url", return_value=None),
patch("litellm.proxy.auth.auth_utils._has_user_setup_sso", return_value=False),
patch(
"litellm.proxy.proxy_server.general_settings",
{"hide_default_credentials_hint": True},
),
patch.dict(os.environ, {"DISABLE_ADMIN_UI": "false"}, clear=False),
):
os.environ.pop("LITELLM_HIDE_DEFAULT_CREDENTIALS_HINT", None)
response = client.get("/.well-known/litellm-ui-config")
assert response.status_code == 200
data = response.json()
assert data["hide_default_credentials_hint"] is True
def test_ui_discovery_endpoints_is_control_plane_false_when_no_workers():
app = FastAPI()
app.include_router(router)

View file

@ -188,28 +188,30 @@ function LoginPageContent() {
<Text type="secondary">Access your LiteLLM Admin UI.</Text>
</div>
<Alert
message="Default Credentials"
description={
<>
<Paragraph className="text-sm">
By default, Username is <code className="bg-gray-100 px-1 py-0.5 rounded text-xs">admin</code> and
Password is your set LiteLLM Proxy
<code className="bg-gray-100 px-1 py-0.5 rounded text-xs">MASTER_KEY</code>.
</Paragraph>
<Paragraph className="text-sm">
Need to set UI credentials or SSO?{" "}
<a href="https://docs.litellm.ai/docs/proxy/ui" target="_blank" rel="noopener noreferrer">
Check the documentation
</a>
.
</Paragraph>
</>
}
type="info"
icon={<InfoCircleOutlined />}
showIcon
/>
{!uiConfig?.hide_default_credentials_hint && (
<Alert
message="Default Credentials"
description={
<>
<Paragraph className="text-sm">
By default, Username is <code className="bg-gray-100 px-1 py-0.5 rounded text-xs">admin</code> and
Password is your set LiteLLM Proxy
<code className="bg-gray-100 px-1 py-0.5 rounded text-xs">MASTER_KEY</code>.
</Paragraph>
<Paragraph className="text-sm">
Need to set UI credentials or SSO?{" "}
<a href="https://docs.litellm.ai/docs/proxy/ui" target="_blank" rel="noopener noreferrer">
Check the documentation
</a>
.
</Paragraph>
</>
}
type="info"
icon={<InfoCircleOutlined />}
showIcon
/>
)}
{error && <Alert message={error} type="error" showIcon />}

View file

@ -285,6 +285,7 @@ export interface LiteLLMWellKnownUiConfig {
auto_redirect_to_sso: boolean;
admin_ui_disabled: boolean;
sso_configured: boolean;
hide_default_credentials_hint?: boolean;
is_control_plane?: boolean;
workers?: WorkerInfo[];
}