Intelligence
criticalVulnerabilityActive

SiYuan Bazaar Stored XSS via Unescaped Package Metadata Leading to Electron RCE

SiYuan's Bazaar marketplace fails to HTML-escape package `name` and `version` fields before rendering them to DOM via `innerHTML`, enabling stored XSS that escalates to OS command execution due to permissive Electron security configuration (nodeIntegration enabled, contextIsolation disabled).

S
Sebastion

CVE References

Affected

SiYuan/SiYuan (all versions prior to patch)

Vulnerability Description

This is a stored cross-site scripting (XSS) vulnerability in the package metadata rendering pipeline. The root cause is a gap in output encoding: the sanitizePackageDisplayStrings function in kernel/bazaar/package.go escapes Author, DisplayName, and Description fields but omits Name and Version. These unescaped strings are subsequently interpolated into HTML template literals (${item.preferredName}, ${data.name}, v${data.version}) and assigned directly to innerHTML in app/src/config/bazaar.ts, causing the browser parser to execute any embedded HTML/JavaScript. A secondary code path exists where displayName falls back to the unescaped pkg.Name when the locale map is empty, widening the attack surface.

PoC Significance & Reliability

The PoC demonstrates zero-click stored XSS: opening the Marketplace tab and viewing the Downloaded plugins list is sufficient to trigger payload execution—no user interaction with Install/Update buttons is required. Payloads persist in the package metadata (plugin.json, theme.json, etc.) and are executed every time the marketplace UI renders. The precondition is that a malicious or compromised package must be in the Bazaar repository or reachable via package distribution, but once present, any user browsing the marketplace is vulnerable. Reliability is near 100% given the deterministic nature of innerHTML assignment.

Detection Guidance

Log indicators:

  • Monitor app/src/config/bazaar.ts for calls to innerHTML without prior sanitization.
  • Watch for anomalies in plugin.json, theme.json, template.json, widget.json, or icon.json files where name or version fields contain HTML tag delimiters (<, >, script, iframe, event handlers like onerror=).
  • Scan Bazaar repository metadata for packages with suspicious characters in name/version: regex patterns like name: ".*[<>'\"].*" or version: ".*[<>'\"].*".
  • Monitor Node.js child process spawning from Electron renderer contexts; XSS in this configuration grants direct access to child_process.
  • Search endpoint logs for unusual marketplace queries or bulk downloads of packages with malformed metadata.

YARA signatures (metadata-level):

rule SiYuan_Bazaar_XSS_Payload {
  strings:
    $name_tag = /"name"\s*:\s*"[^"]*[<>'\"][^"]*"/ nocase
    $version_tag = /"version"\s*:\s*"[^"]*[<>'\"][^"]*"/ nocase
    $script = /script|onerror|onload|innerHTML/ nocase
  condition:
    any of them
}

Mitigation Steps

  1. Immediate patch: Update kernel/bazaar/package.go to escape Name and Version in sanitizePackageDisplayStrings; apply the same HTML entity encoding used for Author and Description.
  2. Frontend hardening: Replace innerHTML assignments with textContent for all package metadata fields, or use DOM methods like document.createTextNode() and appendChild().
  3. Electron security: Set nodeIntegration: false, contextIsolation: true, and webSecurity: true in app/electron/main.js:407-411 (breaking change, requires preload script refactoring).
  4. Input validation: Reject or strip package metadata containing HTML/XML-like syntax at ingestion into the Bazaar.
  5. Content Security Policy (CSP): Implement a strict CSP header preventing inline script execution and restricting Node.js API access from renderer context.
  6. Repository audit: Scan all existing packages in Bazaar for malicious payloads in name and version fields.

Risk Assessment

Likelihood of exploitation in the wild: High. Bazaar is a public, community-driven marketplace; attackers can upload or compromise packages to distribute payloads. The zero-click nature and permissive Electron configuration make this low-friction for mass exploitation. Threat actor interest: Critical. This is a supply-chain attack vector enabling arbitrary code execution under the user's account with persistent payload storage. Advanced persistent threat (APT) actors, ransomware operators, and data-exfiltration groups would find this highly valuable. No user interaction required beyond opening a UI tab, making it suitable for automated worm-like distribution. The window for exploitation remains open until all users patch and Bazaar contents are sanitized.