GHSA-36V8-MPJM-8J5R

Vulnerability from github – Published: 2026-09-03 21:21 – Updated: 2026-09-03 21:21
VLAI
Summary
SiYuan: Cross-boundary content disclosure via getBacklinkDoc/getBackmentionDoc (publish mode): reader-reachable rendered DOM of publish-forbidden docs; sibling list endpoints are filtered
Details

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 <admin-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.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/siyuan-note/siyuan/kernel"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.0.0-20260721014413-f45749a7ef6e"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-68586"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-03T21:21:19Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "**CVE:** This vulnerability corresponds to [CVE-2026-68586](https://nvd.nist.gov/vuln/detail/CVE-2026-68586).\n\n### Summary\n\nThe 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.\n\nBoth content endpoints are gated by `CheckAuth` only, reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`.\n\n### Details\n\nThe asymmetry between the list and content sides is the tell that this is an oversight, not intended behavior:\n\n| Endpoint | Returns | Publish-access filter | Route |\n|---|---|---|---|\n| `getBacklink` | list (`*Path`) | `FilterPathsByPublishAccess` - present | `CheckAuth` |\n| `getBacklink2` | list (`*Path`) | `FilterPathsByPublishAccess` - present | `CheckAuth` |\n| `getBacklinkDoc` | rendered DOM | none | `CheckAuth` |\n| `getBackmentionDoc` | rendered DOM | none | `CheckAuth` |\n\n`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.\n\nA 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`.\n\n### Proof of Concept\n\nReproduced 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.\n\n**1. Mark the target document publish-forbidden (admin action, the boundary that should block reads):**\n```\nPOST http://127.0.0.1:6806/api/filetree/setPublishAccess\nAuthorization: Token \u003cadmin-token\u003e\n{\"id\":\"REFTREEID\",\"visible\":false,\"password\":\"\",\"disable\":true}\n```\n\n**2. Baseline: the list endpoint correctly hides the forbidden doc from the reader (anonymous, port 6808):**\n```\nPOST http://127.0.0.1:6808/api/ref/getBacklink2\n{\"id\":\"DEFID\",\"k\":\"\",\"mk\":\"\"}\n```\nThe returned backlinks do not include the forbidden document `D`, the list side is filtered.\n\n**3. Disclosure: the content endpoint returns the forbidden doc\u0027s blocks anyway (anonymous, port 6808):**\n```\nPOST http://127.0.0.1:6808/api/ref/getBacklinkDoc\n{\"defID\":\"DEFID\",\"refTreeID\":\"REFTREEID\",\"keyword\":\"\"}\n```\nReturns 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.\n\n### Impact\n\nAn anonymous reader (publish mode with auth disabled) or any publish `RoleReader`, can read the rendered content of a publish-forbidden document\u0027s referencing blocks, defeating a boundary the administrator explicitly configured, and can determine whether a forbidden document references a given block (a reference-existence oracle).\n\n**Precondition (stated honestly):** the request requires `refTreeID` (the forbidden document\u0027s 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.\n\nImpact 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.\n\n### Suggested fix\n\nApply the same publish-access check the list siblings use. In `getBacklinkDoc`/`getBackmentionDoc`, filter each `Backlink` by its source document\u0027s 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.",
  "id": "GHSA-36v8-mpjm-8j5r",
  "modified": "2026-09-03T21:21:20Z",
  "published": "2026-09-03T21:21:19Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-36v8-mpjm-8j5r"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-68586"
    },
    {
      "type": "WEB",
      "url": "https://github.com/siyuan-note/siyuan/commit/f45749a7ef6e385f6e2af6b7dd12429d56d46f32"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/siyuan-note/siyuan"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/siyuan-before-content-disclosure-via-getbacklinkdoc"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "SiYuan: Cross-boundary content disclosure via getBacklinkDoc/getBackmentionDoc (publish mode): reader-reachable rendered DOM of publish-forbidden docs; sibling list endpoints are filtered"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline

Sightings and recorded dates, grouped by day · UTC

JSON
How durations are calculated

Following the VTEM framework (Black Hat USA 2015), time to patch starts when the vendor or a coordinator was informed, total time to patch at discovery, and disclosure to patch at public disclosure; vendor response time runs from the report to its acknowledgement. Time to exploit and time unpatched start at the earliest discovery or report, falling back to public disclosure. Unpatched time ends at the first recorded patch, or the calculation time when no patch is recorded. Exploitation to patch shows the interval between those two events; a published proof of concept is a public exploit, not exploitation.

Each result shows its source dates. A negative interval means the end event came first; when date-only inputs leave the order open, the result says so. Date-only inputs are approximate. The earliest evidence wins: KEV report dates and sightings are labelled as such. Records describing another vulnerability are listed but never calculated from, and a PoC alone does not establish exploitation. Missing patch evidence does not prove that no patch exists. Filters below change the event list only.

Events included in the timeline

Loading timeline…


    Loading…

    Loading…

    Loading…

    Related by attack behaviour

    Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.