diff --git a/src/lib/components/chat/Messages/Markdown/MarkdownInlineTokens.svelte b/src/lib/components/chat/Messages/Markdown/MarkdownInlineTokens.svelte index 0daf389eec..01536a7bef 100644 --- a/src/lib/components/chat/Messages/Markdown/MarkdownInlineTokens.svelte +++ b/src/lib/components/chat/Messages/Markdown/MarkdownInlineTokens.svelte @@ -96,7 +96,7 @@ > {/if} {:else if token.type === 'image'} - {token.text} + {token.text} {:else if token.type === 'strong'} {:else if token.type === 'em'} diff --git a/src/lib/components/common/Image.svelte b/src/lib/components/common/Image.svelte index 3007d70caa..76cc6ccd1e 100644 --- a/src/lib/components/common/Image.svelte +++ b/src/lib/components/common/Image.svelte @@ -9,6 +9,7 @@ export let src = ''; export let alt = ''; + export let allowExternal = false; export let className = ` w-full ${($settings?.highContrastMode ?? false) ? '' : 'outline-hidden focus:outline-hidden'}`; @@ -20,7 +21,7 @@ const i18n = getContext('i18n'); let _src = ''; - $: _src = safeImageUrl(src.startsWith('/') ? `${WEBUI_BASE_URL}${src}` : src); + $: _src = safeImageUrl(src.startsWith('/') ? `${WEBUI_BASE_URL}${src}` : src, allowExternal); let showImagePreview = false; diff --git a/src/lib/utils/safeImageUrl.ts b/src/lib/utils/safeImageUrl.ts index 82a834ca07..1f63410fb0 100644 --- a/src/lib/utils/safeImageUrl.ts +++ b/src/lib/utils/safeImageUrl.ts @@ -11,18 +11,20 @@ const PLACEHOLDER_IMAGE = '/favicon.png'; * - data:image/* URIs * - Same-origin URLs (starting with WEBUI_BASE_URL) * - Gravatar URLs (https://www.gravatar.com/avatar/) + * - External HTTP(S) URLs when allowExternal is true * - * All other URLs (including arbitrary http(s):// origins) are rejected to - * prevent client-side IP/UA/Referer leaks to attacker-controlled servers. + * All other URLs (including arbitrary http(s):// origins by default) are + * rejected to prevent client-side IP/UA/Referer leaks to attacker-controlled servers. */ -export function safeImageUrl(url: string): string { +export function safeImageUrl(url: string, allowExternal = false): string { if (!url || url === '') { return `${WEBUI_BASE_URL}${PLACEHOLDER_IMAGE}`; } if ( - url.startsWith(WEBUI_BASE_URL) || + (WEBUI_BASE_URL && url.startsWith(WEBUI_BASE_URL)) || url.startsWith('https://www.gravatar.com/avatar/') || + (allowExternal && /^https?:\/\//i.test(url)) || url.startsWith('data:') || url.startsWith('/') ) {