From b8a141cefd2b0aba2959a2aae42f7a465575577e Mon Sep 17 00:00:00 2001 From: user <70670632+stuxf@users.noreply.github.com> Date: Thu, 30 Apr 2026 11:34:25 -0700 Subject: [PATCH] fix(static-assets): stop serving stale logo cache --- litellm/proxy/proxy_server.py | 18 +----------------- tests/test_litellm/proxy/test_proxy_server.py | 19 +++++++++---------- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index b65455e567..828a4747bd 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -12229,7 +12229,7 @@ def get_logo_url(): directly by the browser from a public/internal CDN. Local file paths set via ``UI_LOGO_PATH`` are NOT returned: they are admin- only filesystem details, the dashboard falls back to ``/get_image`` - which serves the file (with path containment) instead. Without + which serves the file only when it is a supported image. Without this filter, the unauthenticated endpoint would disclose internal hostnames or filesystem paths to any caller. """ @@ -12275,9 +12275,6 @@ async def get_image(): if assets_dir != current_dir and not os.path.exists(default_logo): default_logo = default_site_logo - cache_dir = assets_dir if os.access(assets_dir, os.W_OK) else current_dir - cache_path = os.path.join(cache_dir, "cached_logo.jpg") - logo_path = os.getenv("UI_LOGO_PATH", default_logo) verbose_proxy_logger.debug("Reading logo from path: %s", logo_path) @@ -12302,19 +12299,6 @@ async def get_image(): if logo_path.startswith(("http://", "https://")): return RedirectResponse(url=logo_path) - # [OPTIMIZATION] For default logo, check if the cached image exists. - # Validate the cache before serving so stale pre-fix cache files cannot - # keep exposing non-image responses fetched before this hardening. - if os.path.exists(cache_path): - safe_cache = resolve_validated_local_image_path(cache_path) - if safe_cache is not None: - safe_cache_path, media_type = safe_cache - return FileResponse(safe_cache_path, media_type=media_type) - verbose_proxy_logger.warning( - "Ignoring cached logo at %s because it is not a supported image file", - cache_path, - ) - # Default logo (resolved from the bundled asset, not user-controlled). safe_logo = resolve_validated_local_image_path(logo_path) if safe_logo is not None: diff --git a/tests/test_litellm/proxy/test_proxy_server.py b/tests/test_litellm/proxy/test_proxy_server.py index 356ab4a4b0..d482fd1c51 100644 --- a/tests/test_litellm/proxy/test_proxy_server.py +++ b/tests/test_litellm/proxy/test_proxy_server.py @@ -4073,10 +4073,10 @@ async def test_get_image_custom_local_logo_bypasses_cache(monkeypatch, tmp_path) @pytest.mark.asyncio -async def test_get_image_default_logo_still_uses_cache(monkeypatch, tmp_path): +async def test_get_image_default_logo_ignores_stale_cache(monkeypatch, tmp_path): """ - Test that when UI_LOGO_PATH is NOT set (default logo), the cache - optimization still works — cached_logo.jpg is returned if it exists. + Test that when UI_LOGO_PATH is NOT set, stale pre-fix cached_logo.jpg + files are ignored and the default logo is served. """ from unittest.mock import patch @@ -4105,7 +4105,8 @@ async def test_get_image_default_logo_still_uses_cache(monkeypatch, tmp_path): len(calls_to_file_response) == 1 ), "FileResponse should be called exactly once" served_path = calls_to_file_response[0] - assert served_path == str(cache_path.resolve()) + assert served_path != str(cache_path.resolve()) + assert served_path.endswith("logo.jpg") @pytest.mark.asyncio @@ -4114,14 +4115,12 @@ async def test_get_image_custom_logo_missing_falls_through_to_default( ): """ Test that when UI_LOGO_PATH points to a non-existent local file, - get_image falls through to the cache/default logo instead of failing. + get_image falls through to the default logo instead of failing. """ from unittest.mock import patch from litellm.proxy.proxy_server import get_image - cache_path = tmp_path / "cached_logo.jpg" - cache_path.write_bytes(b"\xff\xd8\xff cached logo") custom_logo_path = tmp_path / "nonexistent_logo.jpg" monkeypatch.setenv("UI_LOGO_PATH", str(custom_logo_path)) monkeypatch.delenv("LITELLM_NON_ROOT", raising=False) @@ -4147,7 +4146,7 @@ async def test_get_image_custom_logo_missing_falls_through_to_default( assert served_path != str( custom_logo_path ), "Should not attempt to serve a non-existent custom logo" - assert served_path == str(cache_path.resolve()) + assert served_path.endswith("logo.jpg") @pytest.mark.asyncio @@ -4156,8 +4155,8 @@ async def test_get_image_custom_logo_missing_no_cache_serves_default( ): """ Test that when UI_LOGO_PATH points to a non-existent file AND there is no - cached_logo.jpg, get_image serves the default logo instead of the - non-existent custom path. + cached_logo.jpg, get_image serves the default logo instead of the non-existent + custom path. """ from unittest.mock import patch