CVE-2026-54067
Summary
A CSS snippet body containing </style> breaks out of its surrounding <style> tag when renderSnippet() interpolates it via insertAdjacentHTML. A payload like </style><img src=x onerror="..."> runs arbitrary JavaScript in the renderer. On Electron desktop builds the renderer runs with nodeIntegration:true, so require('child_process') is reachable from the injected handler and the XSS chains to host RCE. Snippets sync via the workspace repository, so an attacker with write access to any synced workspace plants the payload once and it fires on every device that pulls.
The bug also bypasses the user's enabledCSS / enabledJS separation. A user who turned enabledJS off was making a deliberate call not to run untrusted JavaScript; the CSS path runs it anyway.
Details
Affected:
- HEAD 96dfe0b (v3.6.5, 2026-04-21)
- Sink: app/src/config/util/snippets.ts:32
- Source: /api/snippet/getSnippet, backed by data/snippets/conf.json
- Default config: EnabledCSS: true, EnabledJS: true at kernel/conf/snippet.go:26-27
- Electron config: nodeIntegration:true, contextIsolation:false, webSecurity:false on every BrowserWindow in app/electron/main.js:307,408-411,1107-1110,1150-1153,1322
The write path stores raw content. kernel/api/snippet.go:107-130 copies Content from the request straight into the snippet record with no HTML escape, no </style> check, no type-specific validation:
snippet := &conf.Snippet{
ID: m["id"].(string),
Name: m["name"].(string),
Type: m["type"].(string),
Content: m["content"].(string),
Enabled: m["enabled"].(bool),
}
Storage is workspace-internal and syncs. kernel/model/repository.go:1748,1798 reference data/snippets/conf.json, so the malicious record propagates to every sync peer.
The renderer reads the snippet back through /api/snippet/getSnippet and interpolates it into a <style> tag, raw. app/src/config/util/snippets.ts:32, called on app boot and on the reloadSnippet WebSocket event:
fetchPost("/api/snippet/getSnippet", {type: "all", enabled: 2}
⚡ Watch CVE-2026-54067
Get an email if CVE-2026-54067 is added to CISA KEV, gains public exploit code, or a new advisory cites it — max one per day, one-click unsubscribe.
Exploitation outlook
- Low exploitation risk0.31% 30-day exploitation probability — currently an unlikely target, but scores change as exploit code circulates. Riskier than 23% of all EPSS-scored CVEs.
Advisory coverage (1)
- criticalGHSA-mvjr-vv3c-w4qv: SiYuan: Stored XSS to RCE via CSS-snippet breakout in renderSnippet()ghsa · 2026-07-10
External references
Embed the live status
— this badge updates automatically when the KEV or exploit status changes. How to embed it →
[](https://www.csirts.com/cve/CVE-2026-54067)