Skip to main content
VulnerabilityPublished Updated

CVE-2026-72804: siyuan · Information Exposure

Affects siyuanSource CVE Database V5

0
Compare

Not known to be exploited · CVSS 9.2 Critical : upgrade to 3.7.4 as a priority.

Data as of 8 Nov 2026, 23:24 UTC

CVSS 4.0 base score
9.2Critical
How severe the flaw is on the 0–10 CVSS scale.
EPSS
0.4% chance of exploitation in 30 days – higher than 37% of CVEsExploit Prediction Scoring System: the likelihood attackers will use this flaw soon.
Patch
Available – fixed in 3.7.4
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N

Exploitation evidence

  1. Disclosed: evidence found.

    CVE published 12 Aug 2026

  2. Detectable: no evidence on record.

    No public nuclei template indexed

  3. Weaponized: no evidence on record.

    No public exploit code indexed in Metasploit or Exploit-DB

  4. Exploited in the wild: no evidence on record.

    Not in CISA KEV and no source reports exploitation

  5. Observed by OffSeq Mirage: no evidence on record.

    No attack traffic recorded by OffSeq Mirage sensors

A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 8 Nov 2026.

What to do

Upgrade siyuan to 3.7.4.

Affected software

ProductAffectedFixed in
siyuan-notesiyuanAffected
  • <3.7.4
Fixed in
  • 3.7.4

Description

**CVE:** This vulnerability corresponds to [CVE-2026-72804](https://nvd.nist.gov/vuln/detail/CVE-2026-72804). ### Summary `getGraph` and `getLocalGraph` filter reader sessions against the *visibility* tier only and never check the publish password. Password-protected documents are `Visible = true`, so their graph nodes survive the filter and graph nodes are block-level and carry the block's actual content. An anonymous reader who has never supplied a document's password can therefore retrieve that document's per-block content and its reference/backlink topology. Both endpoints are `CheckAuth`-only, so they are reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`. ### Details Both handlers filter with the invisible-tier set only: ```go publishIgnore := model.GetInvisiblePublishAccess(publishAccess) // Visible tier ONLY nodes, links = model.FilterGraphByPublishIgnore(publishIgnore, nodes, links) ``` `FilterGraphByPublishIgnore` (`kernel/model/publish_access.go:849`) drops a node only when `!CheckPathAccessableByPublishIgnore(node.Box, node.Path, publishIgnore)`. There is no password evaluation anywhere in the graph code grepping `graph.go` for `CheckPublishAuthCookie` or `password` returns nothing. Because password-protected documents are `Visible = true`, their nodes pass the filter unchanged. **The nodes carry content, not just titles.** `genTreeNodes` emits one node per block, and `nodeTitleLabel` sets `node.Title = node.Label = block.Content` (`kernel/model/graph.go:673-678`). So each surviving node exposes the block's text. This is materially broader than the by-design listing behaviour: `listDocsByPath` intentionally exposes protected document *titles* (protected means "publicly visible, password required to access"), but the graph endpoints expose per-block *content* and the full link/reference topology, which listing never does. Verified at `origin/master`: `FilterGraphByPublishIgnore` contains only the `CheckPathAccessableByPublishIgnore` call; `graph.go` contains no password check; both routes are registered `CheckAuth` without `CheckAdminRole`. ### Proof of Concept Precondition: publish mode enabled (default port 6808); anonymous when `Publish.Auth.Enable` is `false`, otherwise any publish reader account. A document is marked **protected** (visible, password set) and contains blocks with distinctive content. No password is supplied in any request below. **Targeted: one protected document's content and reference structure:** ``` POST http://127.0.0.1:6808/api/graph/getLocalGraph {"id":"<PROTECTED_DOC_ID>"} ``` Returns nodes whose `Title`/`Label` contain the protected document's per-block content, plus its links/backlinks. **Workspace-wide: every protected document:** ``` POST http://127.0.0.1:6808/api/graph/getGraph {} ``` Returns block-level nodes for every protected document in the workspace, together with the complete link graph. **Control:** requesting the same document through the normal content path returns the password placeholder confirming the password gate is enforced elsewhere and omitted here. ### Impact An anonymous reader (publish mode with auth disabled) or any publish `RoleReader` can read the block-level content of every password-protected document in the workspace, plus the full reference/backlink topology, without ever supplying a password. This defeats the publish-password control for the graph subsystem. Confidentiality-only, no modification. ### Suggested fix Extend the graph filter to evaluate the password tier in addition to visibility: in `FilterGraphByPublishIgnore`, drop a node unless the document's publish password is unset or the caller presents a valid publish-auth cookie for it (`password == "" || CheckPublishAuthCookie(...)`), matching the sibling filters that enforce both tiers. Consider also excluding block content from node `Title`/`Label` for reader sessions, so the graph conveys structure without document text.

References

Community reviews

Loading reviews…