From 2d9939ed4964bb9e5b80018f1739708fc4e55092 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 10 May 2026 17:59:32 +0200 Subject: [PATCH] chore: add validate_url() to get_image_data() for cohort consistency hardening (#24518) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: add validate_url() to get_image_data() for cohort consistency hardening `get_image_data()` in `backend/open_webui/routers/images.py` fetches the URL returned by the configured image generation API directly via `session.get(data)` without first calling `validate_url()`. The sibling `load_url_image()` in the same file (called from /images/edit) calls `validate_url(data)` first — that gate was added under GHSA-jgx9-jr5x-mvpv. The two functions handle structurally identical input (an attacker-or-server-supplied URL string) and should enforce the same SSRF gate as a matter of code hygiene. In the current call graph, the URL passed to `get_image_data()` comes from the admin-configured image generation API's response, so an exploitable SSRF chain additionally requires admin-side trust delegation (misconfigured/untrusted upstream image API, or a custom OpenAI-compatible server that reflects user input into response URLs). That makes the missing call a defense-in-depth gap rather than a vulnerability per SECURITY.md Rule 9 — a position the GHSA-h7cc-wwjp-5xqh advisory is being closed under. This change is hardening: it brings the two image-fetch helpers into alignment so any future caller that begins passing user-influenced URLs into `get_image_data()` is gated by the same private-IP / loopback / metadata-IP filter the rest of the codebase enforces. Surface raised by brodmart in GHSA-h7cc-wwjp-5xqh. Co-authored-by: brodmart * chore: trim comment --------- Co-authored-by: brodmart --- backend/open_webui/routers/images.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/open_webui/routers/images.py b/backend/open_webui/routers/images.py index f61970f3de..e55b7c5798 100644 --- a/backend/open_webui/routers/images.py +++ b/backend/open_webui/routers/images.py @@ -442,6 +442,8 @@ GenerateImageForm = CreateImageForm # Alias for backward compatibility async def get_image_data(data: str, headers=None): try: if data.startswith('http://') or data.startswith('https://'): + # Defense-in-depth: gate before fetch (mirrors load_url_image). + validate_url(data) session = await get_session() async with session.get( data,