Every CVE Search/ Get API key

CVE-2026-45401

Open WebUI: SSRF Bypass via HTTP Redirect Following in Web-Fetch and Image-Load Endpoints

8.5 HighPublic exploitFix available

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.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
Low
Availability
None

Exploit likelihood

0.30%Up 0.3 points since May 16, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.5

Open WebUI: SSRF Bypass via HTTP Redirect Following in Web-Fetch and Image-Load Endpoints

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.

Record
CVE-2026-45401
CVSS 3.1
8.5 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
EUVDEUVD-2026-30631 8.5

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.

Record
EUVD-2026-30631
CVSS 3.1
8.5 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-rh5x-h6pp-cjj6 8.5

Open WebUI has a SSRF Bypass via HTTP Redirect Following in Web-Fetch and Image-Load Endpoints (not addressed by CVE-2025-65958)

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.

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:

curl -X POST https://<target>/api/chat/completions \
  -H "Authorization: Bearer <any_user_token>" \
  -H "Content-Type:…
Record
GHSA-rh5x-h6pp-cjj6
CVSS 3.1
8.5 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
NVD 8.5

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.

Record
CVE-2026-45401
CVSS 3.1
8.5 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
OSV 8.5

Open WebUI: SSRF Bypass via HTTP Redirect Following in Web-Fetch and Image-Load Endpoints

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.

Record
CVE-2026-45401
CVSS 3.1
8.5 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
OSVGHSA-rh5x-h6pp-cjj6 8.5

Open WebUI has a SSRF Bypass via HTTP Redirect Following in Web-Fetch and Image-Load Endpoints (not addressed by CVE-2025-65958)

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.

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:

curl -X POST https://<target>/api/chat/completions \
  -H "Authorization: Bearer <any_user_token>" \
  -H "Content-Type:…
Record
GHSA-rh5x-h6pp-cjj6
CVSS 3.1
8.5 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
OSVPYSEC-2026-2755 8.5

Open WebUI has a SSRF Bypass via HTTP Redirect Following in Web-Fetch and Image-Load Endpoints (not addressed by CVE-2025-65958)

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.

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:

curl -X POST https://<target>/api/chat/completions \
  -H "Authorization: Bearer <any_user_token>" \
  -H "Content-Type:…
Record
PYSEC-2026-2755
CVSS 3.1
8.5 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
open-webui
PyPI
through 0.9.4
0.9.5
open-webui
PyPI
before 0.9.5, plus listed versions
0.1.1240.1.1250.2.00.2.10.2.2
Show 45 moreShow less
0.2.30.2.40.2.50.3.00.3.10.3.100.3.120.3.130.3.140.3.150.3.160.3.170.3.17.dev20.3.17.dev30.3.17.dev40.3.17.dev50.3.180.3.190.3.20.3.200.3.210.3.220.3.230.3.240.3.250.3.260.3.270.3.27.dev10.3.27.dev20.3.27.dev30.3.280.3.290.3.30.3.300.3.30.dev10.3.30.dev20.3.310.3.31.dev10.3.320.3.330.3.33.dev10.3.340.3.350.3.40.3.5
0.9.5

Public exploits

Links only. Every CVE stores no exploit code.

Public exploits
SourceLinkDate
PoC in GitHubnayakchinmohan/CVE-2026-454012026-05-26

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV, PoC in GitHub

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-45401 is a high vulnerability (CVSS 8.5) in Openwebui Open Webui, published May 14, 2026. Public exploit code exists. EPSS puts the chance of exploitation in the next 30 days at 0.30%, the 22nd percentile. Fixed in open-webui 0.9.5.

References

This page doesn't list everything

Left out here: 106 versions and the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open