diff --git a/ui/litellm-dashboard/src/app/page.tsx b/ui/litellm-dashboard/src/app/page.tsx index 1aa555be4fe..93b7b19deae 100644 --- a/ui/litellm-dashboard/src/app/page.tsx +++ b/ui/litellm-dashboard/src/app/page.tsx @@ -56,10 +56,12 @@ import { ConfigProvider, theme } from "antd"; function deleteCookie(name: string, path = "/") { // Best-effort client-side clear (works for non-HttpOnly cookies without Domain) document.cookie = `${name}=; Max-Age=0; Path=${path}`; - try { - sessionStorage.removeItem(name); - } catch { - // sessionStorage may be unavailable + if (name === "token") { + try { + sessionStorage.removeItem(name); + } catch { + // sessionStorage may be unavailable + } } } diff --git a/ui/litellm-dashboard/src/utils/cookieUtils.ts b/ui/litellm-dashboard/src/utils/cookieUtils.ts index 4282d645c0e..8566f0d1aa7 100644 --- a/ui/litellm-dashboard/src/utils/cookieUtils.ts +++ b/ui/litellm-dashboard/src/utils/cookieUtils.ts @@ -56,6 +56,10 @@ export function clearTokenCookies() { * Stores the login token in sessionStorage. * This ensures the token is available even when a reverse proxy adds HttpOnly * to server-set cookies, making them invisible to JavaScript. + * + * Note: sessionStorage is per-tab, so users behind an HttpOnly proxy must log + * in once per tab. We intentionally avoid localStorage here because it persists + * after browser close and is readable by any injected script (XSS). */ export function storeLoginToken(token: string) { if (typeof window === "undefined") return;