Every CVE Search/ Get API key

CVE-2026-45318

Open WebUI: Stored XSS via unsanitized Office/Excel/DOCX file preview rendering ({@html} without DOMPurify)

5.4 MediumFix available

Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.3, his advisory tracks a regression of the original Excel-preview XSS (CVE-2026-44549). 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 This vulnerability is fixed in 0.9.3.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
Required

What an attacker can affect

Confidentiality
Low
Integrity
Low
Availability
None

Exploit likelihood

0.21%Up 0.2 points since May 16, 2026
90%50%10%1%

What each source reports

CVE List Score used 5.4

Open WebUI: Stored XSS via unsanitized Office/Excel/DOCX file preview rendering ({@html} without DOMPurify)

Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.3, his advisory tracks a regression of the original Excel-preview XSS (CVE-2026-44549). 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 This vulnerability is fixed in 0.9.3.

Record
CVE-2026-45318
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
EUVDEUVD-2026-30659 5.4

Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.3, his advisory tracks a regression of the original Excel-preview XSS (CVE-2026-44549). 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 This vulnerability is fixed in 0.9.3.

Record
EUVD-2026-30659
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-hcwp-82g6-8wxc 5.4

Open WebUI has stored XSS via unsanitized Office/Excel/DOCX file preview rendering ({@html} without DOMPurify)

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, 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:
    <w:r><w:t><![CDATA[<svg…
    
Record
GHSA-hcwp-82g6-8wxc
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
NVD 5.4

Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.3, his advisory tracks a regression of the original Excel-preview XSS (CVE-2026-44549). 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 This vulnerability is fixed in 0.9.3.

Record
CVE-2026-45318
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSV 5.4

Open WebUI: Stored XSS via unsanitized Office/Excel/DOCX file preview rendering ({@html} without DOMPurify)

Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. Prior to 0.9.3, his advisory tracks a regression of the original Excel-preview XSS (CVE-2026-44549). 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 This vulnerability is fixed in 0.9.3.

Record
CVE-2026-45318
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSVGHSA-hcwp-82g6-8wxc 5.4

Open WebUI has stored XSS via unsanitized Office/Excel/DOCX file preview rendering ({@html} without DOMPurify)

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, 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:
    <w:r><w:t><![CDATA[<svg…
    
Record
GHSA-hcwp-82g6-8wxc
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSVPYSEC-2026-2731 5.4

Open WebUI has stored XSS via unsanitized Office/Excel/DOCX file preview rendering ({@html} without DOMPurify)

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, 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:
    <w:r><w:t><![CDATA[<svg…
    
Record
PYSEC-2026-2731
CVSS 3.1
5.4 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
open-webui
PyPI
through 0.9.2
0.9.3
open-webui
PyPI
before 0.9.3, plus listed versions
0.1.1240.1.1250.2.00.2.10.2.2
Show 45 moreShow less
0.2.30.2.40.2.50.3.00.3.10.3.100.3.120.3.130.3.140.3.150.3.160.3.170.3.17.dev20.3.17.dev30.3.17.dev40.3.17.dev50.3.180.3.190.3.20.3.200.3.210.3.220.3.230.3.240.3.250.3.260.3.270.3.27.dev10.3.27.dev20.3.27.dev30.3.280.3.290.3.30.3.300.3.30.dev10.3.30.dev20.3.310.3.31.dev10.3.320.3.330.3.33.dev10.3.340.3.350.3.40.3.5
0.9.3

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-45318 is a medium vulnerability (CVSS 5.4) in Openwebui Open Webui, published May 14, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.21%, the 11th percentile. Fixed in open-webui 0.9.3.

References

This page doesn't list everything

Left out here: 104 versions and the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open