GitHub Advisoryadvisory · Go

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

HIGH Published 2026-09-03 Modified 2026-09-03 Official page ↗
Aliases
CVE-2026-68586
Ecosystem
Go
Packages
github.com/siyuan-note/siyuan/kernel
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
Weaknesses
CWE-862
Reviewed
2026-09-03

Affected packages

• Go github.com/siyuan-note/siyuan/kernel: < 0.0.0-20260721014413-f45749a7ef6e → fixed in 0.0.0-20260721014413-f45749a7ef6e

Description

CVE: This vulnerability corresponds to CVE-2026-68586. Summary The backlink API splits into list endpoints (which documents reference a block) and content endpoints (the rendered text of those referencing blocks). The list endpoints apply a publish-access filter, the content endpoints do not. As a result, `/api/ref/getBacklinkDoc` and `/api/ref/getBackmentionDoc` return the rendered DOM of blocks belonging to a publish-forbidden document to an anonymous reader, with no access check. Both content endpoints are gated by `CheckAuth` only, reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`. Details The asymmetry between the list and content sides is the tell that this is an oversight, not intended behavior: | Endpoint | Returns | Publish-access filter | Route | |---|---|---|---| | `getBacklink` | list (`*Path`) | `FilterPathsByPublishAccess` - present | `CheckAuth` | | `getBacklink2` | list (`*Path`) | `FilterPathsByPublishAccess` - present | `CheckAuth` | | `getBacklinkDoc` | rendered DOM | none | `CheckAuth` | | `getBackmentionDoc` | rendered DOM | none | `CheckAuth` | `model/backlink.go` contains no publish-access reference anywhere, and `Backlink.DOM` is the rendered HTML of the referencing blocks. `getBacklinkDoc(defID, refTreeID)` returns the rendered content of blocks in `refTreeID` - including a publish-forbidden, publish-disabled, or password-protected document with no access check. The filtered list siblings (`getBacklink`/`getBacklink2`) demonstrate that the publish boundary is meant to apply to this data; the content endpoints simply omit it. A reader is not limited to the filtered backlink list, they call `getBacklinkDoc` directly with any `refTreeID`. This also yields a reference-existence oracle: the response reveals whether the forbidden document `refTreeID` references the block `defID`. Proof of Concept Reproduced on a local instance (SiYuan running locally, publish mode enabled on port 6808, publish Basic Auth disabled). Setup: a publish-forbidden document `D` (`REFTREEID`) whose body contains the unique marker `SECRET_MARKER_77` and which references a block `DEFID` in a separate known document. 1. Mark the target document publish-forbidden (admin action, the boundary that should block reads): ``` POST http://127.0.0.1:6806/api/filetree/setPublishAccess Authorization: Token {"id":"REFTREEID","visible":false,"password":"","disable":true} ``` 2. Baseline: the list endpoint correctly hides the forbidden doc from the reader (anonymous, port 6808): ``` POST http://127.0.0.1:6808/api/ref/getBacklink2 {"id":"DEFID","k":"","mk":""} ``` The returned backlinks do not include the forbidden document `D`, the list side is filtered. 3. Disclosure: the content endpoint returns the forbidden doc's blocks anyway (anonymous, port 6808): ``` POST http://127.0.0.1:6808/api/ref/getBacklinkDoc {"defID":"DEFID","refTreeID":"REFTREEID","keyword":""} ``` Returns HTTP 200; `data.backlinks[].dom` contains `SECRET_MARKER_77`, the rendered content of the publish-forbidden document, returned to an anonymous reader. `getBackmentionDoc` behaves identically for mention-type references. Impact An anonymous reader (publish mode with auth disabled) or any publish `RoleReader`, can read the rendered content of a publish-forbidden document's referencing blocks, defeating a boundary the administrator explicitly configured, and can determine whether a forbidden document references a given block (a reference-existence oracle). Precondition (stated honestly): the request requires `refTreeID` (the forbidden document's ID) and `defID` (a block it references). `defID` may be any published/known block, so if the forbidden document references any public content, `defID` is known and only `refTreeID` need be supplied. Block/document IDs for forbidden documents are also obtainable from other `CheckAuth`-only endpoints that lack the publish-access filter (reported separately). This endpoint alone does not enumerate arbitrary documents; it discloses content once an ID is known. Impact is confidentiality-only: content disclosure plus a reference-existence oracle, no modification. No admin role, CSRF token, or write permission is required. Encrypted notebooks are out of scope. Suggested fix Apply the same publish-access check the list siblings use. In `getBacklinkDoc`/`getBackmentionDoc`, filter each `Backlink` by its source document's box/path via `CheckPathAccessableByPublishIgnore` plus the publish-password cookie check consistent with `FilterPathsByPublishAccess` in `getBacklink`/`getBacklink2`. Any endpoint returning rendered block DOM should enforce the same publish boundary as the corresponding list endpoint.

Related

Alias · CVE (1)

  • CVE-2026-68586 SiYuan before v3.7.3 fails to apply publish-access filters to the getBacklinkDoc and getBackmentionDoc content endpoints… vulnerability

Weakness · CWE (1)

  • CWE-862 Missing Authorization weakness

References