Severity by source
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Network-accessible, any authenticated user, no interaction; scope changes because browser reads from systems outside Open WebUI's domain; no integrity or availability impact applies.
Primary rating from Vendor (https://github.com/open-webui/open-webui).
CVSS VectorVendor: https://github.com/open-webui/open-webui
Lifecycle Timeline
3DescriptionCVE.org
Summary
With the Playwright web loader enabled, Open WebUI opens user-submitted URLs in a real browser and validates the destination address before allowing the request. That check only ran for the top-level page request. Every other request the page issued was passed through unvalidated, so a page could use its own JavaScript to reach addresses the validation exists to block. Because the loader returns the page's final DOM to the requesting user, anything the page read back from those addresses ends up in the web-search or RAG output.
Preconditions
WEB_LOADER_ENGINE=playwright. This is not the default; deployments on the default web loader are unaffected.- A reachable Playwright browser, either local or via
PLAYWRIGHT_WS_URL. - Any authenticated user who can submit a URL for ingestion or trigger a web search. No administrator role is required.
- Something worth reading on a network the browser can reach. A deployment whose browser container has no route to internal services loses nothing here.
Impact
An authenticated user can read HTTP responses from services reachable by the browser process: cloud instance metadata, other containers on the same network, and internal APIs bound to private addresses. The content is returned to the user through the normal web-search or document-ingestion result, so this is a read primitive, not a blind one. It confers no write access and no availability impact, and it does not extend beyond what the browser's network position already allows.
Fix
Fixed in 0.11.0 by commit bef63a2ae. Every intercepted request is now validated, fetched with redirects disabled, re-validated on each redirect hop and then fulfilled, so neither a sub-resource nor a redirect can land on a non-global address. The same change blocks the two paths that never reached the interceptor at all: service-worker requests, via service_workers="block", and WebSocket connections, via a route handler that never connects upstream. Upgrading to 0.11.0 fully resolves the issue; no configuration change is required.
Root cause
Affected component: SafePlaywrightURLLoader in backend/open_webui/retrieval/web/utils.py, in both the sync and async request interceptors. Affected setup: only builds running the Playwright loader engine.
The interceptor was written to guard navigation, and its first action was to return early for any request whose resource type was not document. The intent was that only the page the user asked for needs address validation, but a browser page is not a single request: once the validated document loads, its scripts issue further requests under the page's own control, and those never reached the validation. The address check was therefore applied to the one request the attacker did not need to control, and skipped on every request they did.
Proof of concept
Reported against 0.10.2 by driving the interceptor directly with stand-in route and request objects, one call per resource type, against http://169.254.169.254/latest/meta-data/. The document type is aborted; every other type is continued unvalidated. The browser and the network request were seeded rather than driven end to end; the code path exercised is the one the browser reaches for each sub-resource.
Credits
- @edwardav970 - identified that address validation was applied only to the top-level document request, leaving every sub-resource type unvalidated.
AnalysisAI
Server-Side Request Forgery in Open WebUI versions 0.9.6 through 0.10.x allows any authenticated user to exfiltrate HTTP responses from internal network services - including cloud instance metadata endpoints and container-local APIs - by submitting a crafted URL that triggers unvalidated sub-resource requests through the Playwright browser loader. The SafePlaywrightURLLoader component validated only the top-level navigation request; all subsequent requests issued by page JavaScript bypassed the address check entirely, and the resulting DOM content was returned directly to the requester via the normal web-search or RAG ingestion pipeline. No public exploit or CISA KEV listing is confirmed at time of analysis, though a proof-of-concept was reported against version 0.10.2; the vulnerability is limited to the non-default Playwright loader configuration.
Technical ContextAI
Open WebUI (pip/open-webui) implements a Playwright-based web loader (SafePlaywrightURLLoader in backend/open_webui/retrieval/web/utils.py) that uses Playwright's route interception API to validate URLs before allowing browser requests. The root cause is CWE-918 (Server-Side Request Forgery): the sync and async interceptors both began with an early-return clause that skipped all validation for any resource type other than document. Because a rendered browser page executes JavaScript that independently issues fetch, XHR, image, and script sub-resource requests, an attacker-controlled page can reach arbitrary network addresses - RFC-1918, link-local (169.254.169.254), and container-local - without those requests ever reaching the validation logic. The browser then incorporates responses into the page DOM, which Open WebUI returns as the loader output. The affected CPE is pkg:pip/open-webui, versions >= 0.9.6 and < 0.11.0. Service-worker and WebSocket paths were separately identified as never reaching the interceptor at all, and were also closed in the fix.
RemediationAI
Upgrade to Open WebUI version 0.11.0 or later; this fully resolves the vulnerability and requires no configuration change alongside the upgrade. The fix is confirmed via commit bef63a2ae (https://github.com/open-webui/open-webui/commit/bef63a2ae915571d50d2722a635e8bfa753d7877) and PR #27526 (https://github.com/open-webui/open-webui/pull/27526), which extends validation to every intercepted sub-resource request, disables redirects during fetch, re-validates each redirect hop, and blocks service-worker and WebSocket paths that previously bypassed the interceptor entirely. If an immediate upgrade is not possible, set WEB_LOADER_ENGINE to any value other than playwright to disable the affected loader - this eliminates exposure at the cost of losing JavaScript-rendered page support. As a network-layer compensating control, restrict the browser container's egress to block RFC-1918 ranges, link-local addresses (169.254.0.0/16), and loopback; this removes the practical value of the SSRF but may also prevent legitimate browsing of intranet resources. Neither the configuration change nor the network restriction should substitute for patching.
Same weakness CWE-918 – Server-Side Request Forgery (SSRF)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-52915
GHSA-w2rx-84hp-gg95