Unauthenticated Administrator takeover exfiltrated via the MCP
GHSA advisory for SiYuan v3.7.1 (CVE-2026-66012) describing how the kernel's POST /mcp route registers 31 MCP tools — including a file tool with full read/write/delete/rename/copy over the workspace — gated only by CheckAuth with no admin or read-only check. When the Publish server runs in anonymous mode (a documented configuration for public docs sites), the Publish reverse proxy attaches an anonymous RoleReader JWT to every proxied request, letting an unauthenticated attacker reach /mcp, exfiltrate accessAuthCode/api.token/cookieKey from conf.json, escalate to Administrator, and plant a malicious Electron plugin (nodeIntegration:true, contextIsolation:false) for RCE on the desktop client. Includes a full working PoC and remediation (CheckAdminRole gate, proxy path allowlist, restricting the file tool).
What it is
GHSA-cvhv-7xhj-xjp8 / CVE-2026-66012 in SiYuan v3.7.1 (commit c72ca4cd, released 2026-07-04; official b3log/siyuan:v3.7.1 image). POST /mcp exposes 31 MCP tools gated only by model.CheckAuth — no CheckAdminRole, no CheckReadonly. Classified CWE-862 Missing Authorization, and explicitly the eighth in a class-identical run of Publish Reader-escalation advisories (GHSA-jqwg-75qf-vmf9, -f9cq-v43p-v523, -fmh9-gpqh-g53g, -6r88-8v7q-q4p2, -gmmv-4cc5-wr9r, -px3c-cf92-9g83, -7m5h-w69j-qggg).
Preconditions / Affected
The summary says "anonymous mode" — the page gives the exact flags to check and one detail the summary omits: the authenticated case is also vulnerable.
- Unauthenticated reach:
Conf.Publish.Enable=trueANDConf.Publish.Auth.Enable=false. The proxy atpublish.go:229attaches the anonymous account's RoleReader JWT to every request. - Authenticated reach:
Publish.Auth.Enable=truewith a reader password still exposes the same primitives to any holder of a legitimate reader account — an intended low-privilege viewer becomes Administrator. - Desktop Electron builds ship the same kernel and are equally affected when Publish is enabled.
What to do
No patched version is named — the advisory prescribes source-level fixes. Apply all three:
- Gate the route (
kernel/mcp/server.go:29):
ginServer.POST("/mcp", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, handlePost)- In
kernel/server/proxy/publish.go(lines 228–231), returnhttp.StatusUnauthorizedinstead of forwarding with a Reader token for/mcp,/api/setting,/api/system,/api/import,/api/export,/api/archive,/api/query,/api/sql,/api/bazaar,/api/plugin,/api/skill. A minimal allowlist (/appearance/*,/stage/*,/data/public/*,/api/publish/*) is the safe alternative. - In
kernel/mcp/tools/file.go:86, restrictresolvePathforreadtoWorkspaceDir/temp/siyuan/*.logand refusewrite/delete/rename/copyunless caller is Administrator — or pull the tool from the public registry entirely.
Interim: if you run a public-docs Publish site, disable Publish or front /mcp with an external deny rule until patched.
How the chain lands
The mechanism the summary compresses, with the concrete endpoints:
flowchart TD
A[Unauth attacker → Publish :6808] --> B[proxy attaches anon RoleReader JWT]
B --> C[POST /mcp passes CheckAuth]
C --> D[file tool: read conf/conf.json limit=-1]
D --> E[accessAuthCode + api.token + cookieKey plaintext]
E --> F[loginAuth on admin :6806 → Administrator]
C --> G[file write data/plugins/name/index.js]
G --> H[next desktop launch: window.eval under\nnodeIntegration:true, contextIsolation:false → RCE]The fileRead handler defaults to 200 lines but honors limit=-1 for a full read, so conf.json (all 10913 bytes in the PoC) comes out whole. accessAuthCode unlocks the admin port, api.token is a static bearer accepted at every admin endpoint, cookieKey signs session cookies.
Caveats
- The advisory explicitly scopes itself as not an out-of-workspace-write bug (that is excluded by SECURITY.md); the defect is missing authorization inside the workspace boundary.
- Reproduction was independently confirmed by a cross-verifier on a fresh workspace with identical primitives. Credit: Nguyen Van Hiep (@hypnguyen1209) and Nguyen Quang Ba (@h1bAna), MBBank.
Organisations named here
- GHSA-6r88-8v7q-q4p2
- GHSA-7m5h-w69j-qggg
- GHSA-f9cq-v43p-v523
- GHSA-fmh9-gpqh-g53g
- GHSA-gmmv-4cc5-wr9r
- GHSA-jqwg-75qf-vmf9
- GHSA-px3c-cf92-9g83
CVEs named here
- CVE-2026-66012
Technologies named here
- MCP server
- SiYuan
- curl
- Docker
- Python PoC script
- Model Context Protocol
- Electron
Techniques named here
- Missing Authorization
- Anonymous JWT injection via reverse proxy
- Credential exfiltration from plaintext config
- Arbitrary file write / plugin planting for RCE
- Privilege escalation via stolen accessAuthCode
- Arbitrary file deletion
Also named here
- CWE-862
Related in AppSec
Flowise MCP Security Bypass Enables RCE
Inside an Oracle Database SQL Injection Attack | Huntress
OASIS
