# SiYuan Desktop: Stored XSS in imported .sy.zip content leads to arbitrary command execution

Mixed HTML entity plus raw quote in SiYuan block IAL bypasses attribute escaping, yielding stored XSS in imported .sy.zip that reaches RCE in Electron desktop.

- Payout: Research
- Severity: high
- Program: SiYuan
- Found by: ngocnn97
- Disclosed: 2026-04-01
- CVE: CVE-2026-34585
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-ff66-236v-p4fg
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-ff66-236v-p4fg
- Tags: area:os domain:desktop impact:integrity impact:rce kind:research platform:ghsa sev:high tech:electron tech:go technique:regression technique:source-review vuln:rce vuln:xss

**Target:** SiYuan kernel attribute escaping / Electron desktop renderer
**Root cause:** Regression in escapeNodeAttributeValues: needsEscapeForValue returns false on seeing any known entity (e.g. &) in raw KramdownIAL, so a value mixing an entity with a raw quote skips escaping; previously IAL2Map unescaped entities first and correctly flagged it unsafe.
**Steps:**
1. Start SiYuan Desktop v3.6.1.
2. Craft .sy.zip with a .sy doc containing block IAL `"title": "&\" onmouseenter=\"require('child_process').exec('calc')"`.
3. Right-click a notebook, choose `Import -> SiYuan .sy.zip`, import the archive.
4. Open the imported note and hover the affected paragraph block.
5. Injected JS executes; on Windows calc.exe launches.
**How found:** Code review of escapeNodeAttributeValues in kernel/filesys/tree.go spotted the logic change from IAL2Map-based checking to raw KramdownIAL inspection, and noticed needsEscapeForValue short-circuits to false on any known entity, allowing entity+raw-quote mixes to bypass escaping.
**Exploitation:** Attacker delivers crafted .sy.zip; victim imports via normal GUI and opens the note; renderer inserts IAL value into HTML attribute, breaking out into an onmouseenter handler; hover triggers JS that runs in the Electron renderer with Node integration, invoking child_process.exec for arbitrary command execution.
**Escalation:** Stored XSS in Electron renderer with Node.js integration escalates page-context script execution to OS command execution under the victim's account.
**Insight:** When an escaper short-circuits on detecting an already-encoded entity, test mixed values (entity + raw metacharacter) — the presence of one entity can mask an unescaped quote; also check whether the renderer inserts IAL values into HTML attributes and whether the Electron renderer has Node integration.

