mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-12 08:42:18 +00:00
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:
parent
fc9d789d24
commit
b11e59f3a3
5 changed files with 104 additions and 22 deletions
|
|
@ -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 [],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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] = []
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 />}
|
||||
|
||||
|
|
|
|||
|
|
@ -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[];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue