fix: route external webhook avatar URLs through the profile image endpoint (#29892)
Some checks failed
Python CI / Ruff Format (3.12) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args: free_disk:false name:main suffix:]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args: free_disk:false name:main suffix:]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Has been cancelled
Python CI / Ruff Format (3.11) (push) Has been cancelled
Frontend Build / Format & Build (push) Has been cancelled
Frontend Build / Unit Tests (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:cuda suffix:-cuda]) (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:cuda126 suffix:-cuda126]) (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:main suffix:]) (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:ollama suffix:-ollama]) (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:slim suffix:-slim]) (push) Has been cancelled
Create and publish Docker images with specific build args / notify-helm-charts (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (, main) (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda, cuda) (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda126, cuda126) (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (-ollama, ollama) (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (-slim, slim) (push) Has been cancelled

The channel webhooks modal rendered a webhook's stored profile_image_url straight into an img tag, so opening it sent every viewer's browser to whatever external host that URL named, leaking client IP, User-Agent and Referer no matter how the server was configured.

External URLs now render through the same webhook profile image endpoint the message list already uses, leaving it to the server to decide whether the browser is sent to that host. Locally picked images and the paths Open WebUI assigns itself still render inline, so previewing an upload before saving is unchanged, and the value written back on save is untouched.

This only takes effect together with the companion backend change that gates the endpoint on ENABLE_PROFILE_IMAGE_URL_FORWARDING. Until that lands the endpoint still redirects and the browser still reaches the external host. Also worth knowing: the endpoint matches the scheme case-sensitively, so a URL stored as HTTPS:// falls back to the default image here, which is already what the message list shows for it.

Verified in a browser against a local origin standing in for the external host: with forwarding on the avatar still renders through the endpoint in both places it appears, with forwarding off the browser makes no request to that origin, and picking a new file still previews immediately before saving.
This commit is contained in:
Classic298 2026-09-20 00:03:15 +02:00 • committed by GitHub
parent 7fa705f3b8
commit 043784c2d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -22,6 +22,11 @@
let name = webhook.name;
let image = webhook.profile_image_url || '';
// The server decides whether an external avatar host is fetched.
$: imageSrc = image.toLowerCase().startsWith('http')
? `${WEBUI_API_BASE_URL}/channels/webhooks/${webhook.id}/profile/image`
: image;
// Notify parent when changes occur
$: if (name !== webhook.name || image !== (webhook.profile_image_url || '')) {
onUpdate({ name: name.trim() || webhook.name, profile_image_url: image });
@ -93,7 +98,7 @@
Do not alter, remove, obscure, or replace it except as LICENSE permits:
https://docs.openwebui.com/license. -->
<img
src={image || `${WEBUI_BASE_URL}/static/favicon.png`}
src={imageSrc || `${WEBUI_BASE_URL}/static/favicon.png`}
class="rounded-full size-8 object-cover flex-shrink-0"
alt=""
/>
@ -130,7 +135,7 @@
Do not alter, remove, obscure, or replace it except as LICENSE permits:
https://docs.openwebui.com/license. -->
<img
src={image || `${WEBUI_BASE_URL}/static/favicon.png`}
src={imageSrc || `${WEBUI_BASE_URL}/static/favicon.png`}
class="size-8 object-cover"
alt=""
/>