# SiYuan: Cross-boundary content disclosure via getBacklinkDoc/getBackmentionDoc (publish mode): reader-reachable rendered DOM of publish-forbidden docs; sibling list endpoints are filtered

SiYuan publish mode: getBacklinkDoc/getBackmentionDoc return rendered DOM of publish-forbidden documents to anonymous readers, bypassing the publish-access filter applied to sibling list endpoints.

- Payout: Research
- Severity: high
- Program: SiYuan
- Found by (vendor credit): Shirshakhtml
- Found by: Shirshakhtml
- Disclosed: 2026-09-03
- CVE: CVE-2026-68586
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-36v8-mpjm-8j5r
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-36v8-mpjm-8j5r
- Tags: area:web domain:web impact:data-leak kind:research platform:ghsa sev:high tech:go technique:source-review vuln:access-control vuln:auth-bypass vuln:info-disclosure

**Target:** /api/ref/getBacklinkDoc and /api/ref/getBackmentionDoc kernel endpoints
**Root cause:** Content endpoints (getBacklinkDoc/getBackmentionDoc) are gated only by CheckAuth and omit the FilterPathsByPublishAccess check that their list siblings (getBacklink/getBacklink2) apply, so rendered block DOM of publish-forbidden docs is returned without an access check.
**Steps:**
1. Admin marks doc REFTREEID publish-forbidden: `POST /api/filetree/setPublishAccess` with `{"id":"REFTREEID","visible":false,"password":"","disable":true}`.
2. Baseline: anonymous `POST /api/ref/getBacklink2` with `{"id":"DEFID","k":"","mk":""}` on publish port 6808 — forbidden doc absent from list.
3. Disclosure: anonymous `POST /api/ref/getBacklinkDoc` with `{"defID":"DEFID","refTreeID":"REFTREEID","keyword":""}` returns HTTP 200 with `data.backlinks[].dom` containing the forbidden doc's rendered content (SECRET_MARKER_77).
4. getBackmentionDoc behaves identically for mention-type references.
**How found:** Noticed the asymmetry between list endpoints (which call FilterPathsByPublishAccess) and content endpoints (which do not) in the backlink API, then confirmed model/backlink.go has no publish-access reference and Backlink.DOM is rendered HTML.
**Exploitation:** Anonymous reader (publish mode, Publish.Auth.Enable=false) or any RoleReader token calls the content endpoint directly with a known defID and the forbidden document's refTreeID, receiving rendered DOM of the forbidden document's referencing blocks; response also acts as a reference-existence oracle for whether refTreeID references defID.
**Escalation:** Chained with other CheckAuth-only endpoints that leak block/document IDs (reported separately) to obtain refTreeID, removing the need to know the forbidden doc ID in advance.
**Insight:** When an API splits into 'list' and 'content/detail' endpoints over the same data, audit each sibling independently: authorization filters are often applied to the list path and forgotten on the detail path that returns the actual rendered payload.

