Files
open-webui/src/lib/utils/safeImageUrl.ts
T
Classic298 cfd2888545 fix:image url validation and signout post (#24420)
* refac(routers): reject external URLs in profile/model image handlers

* refac(ui): centralize image URL validation in safeImageUrl helper

* refac(auths): make signout POST-only

* refac: gate external profile image redirect behind ENABLE_PROFILE_IMAGE_URL_FORWARDING

Restore the 302 redirect for external http(s) profile image URLs in
the user and model profile-image endpoints, but gate it behind a new
ENABLE_PROFILE_IMAGE_URL_FORWARDING env flag (default: True).

Existing deployments that rely on external profile image forwarding
continue to work unchanged.  Operators who want to suppress the
redirect (to prevent client-side IP/UA/Referer leaks) can set the
flag to False.
2026-05-09 07:33:31 +09:00

34 lines
939 B
TypeScript

import { WEBUI_BASE_URL } from '$lib/constants';
const PLACEHOLDER_IMAGE = '/favicon.png';
/**
* Validates an image URL against an allowlist of safe patterns and returns
* the URL if trusted, or a placeholder otherwise.
*
* Allowed patterns:
* - Relative paths (starting with '/')
* - data:image/* URIs
* - Same-origin URLs (starting with WEBUI_BASE_URL)
* - Gravatar URLs (https://www.gravatar.com/avatar/)
*
* All other URLs (including arbitrary http(s):// origins) are rejected to
* prevent client-side IP/UA/Referer leaks to attacker-controlled servers.
*/
export function safeImageUrl(url: string): string {
if (!url || url === '') {
return `${WEBUI_BASE_URL}${PLACEHOLDER_IMAGE}`;
}
if (
url.startsWith(WEBUI_BASE_URL) ||
url.startsWith('https://www.gravatar.com/avatar/') ||
url.startsWith('data:') ||
url.startsWith('/')
) {
return url;
}
return `${WEBUI_BASE_URL}${PLACEHOLDER_IMAGE}`;
}