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
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
- https://github.com/siyuan-note/siyuan/security/advisories/GHSA-36v8-mpjm-8j5r web
- https://nvd.nist.gov/vuln/detail/CVE-2026-68586 advisory
- https://github.com/siyuan-note/siyuan/commit/f45749a7ef6e385f6e2af6b7dd12429d56d46f32 web
- https://github.com/siyuan-note/siyuan package
- https://www.vulncheck.com/advisories/siyuan-before-content-disclosure-via-getbacklinkdoc web