| 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}`; | |
| } | |