Files
open-webui/src/lib/components/common/Image.svelte
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

57 lines
1.5 KiB
Svelte

<script lang="ts">
import { WEBUI_BASE_URL } from '$lib/constants';
import { safeImageUrl } from '$lib/utils/safeImageUrl';
import { settings } from '$lib/stores';
import ImagePreview from './ImagePreview.svelte';
import XMark from '$lib/components/icons/XMark.svelte';
import { getContext } from 'svelte';
export let src = '';
export let alt = '';
export let className = ` w-full ${($settings?.highContrastMode ?? false) ? '' : 'outline-hidden focus:outline-hidden'}`;
export let imageClassName = 'rounded-lg';
export let dismissible = false;
export let onDismiss = () => {};
const i18n = getContext('i18n');
let _src = '';
$: _src = safeImageUrl(src.startsWith('/') ? `${WEBUI_BASE_URL}${src}` : src);
let showImagePreview = false;
</script>
<ImagePreview bind:show={showImagePreview} src={_src} {alt} />
<div class=" relative group w-fit flex items-center">
<button
class={className}
on:click={() => {
showImagePreview = true;
}}
aria-label={$i18n.t('Show image preview')}
type="button"
>
<img src={_src} {alt} class={imageClassName} draggable="false" data-cy="image" />
</button>
{#if dismissible}
<div class=" absolute -top-1 -right-1">
<button
aria-label={$i18n.t('Remove image')}
class=" bg-white text-black border border-white rounded-full group-hover:visible invisible transition"
type="button"
on:click={() => {
onDismiss();
}}
>
<XMark className={'size-4'} />
</button>
</div>
{/if}
</div>