CVE-2026-73609
SiYuan before v3.7.4 Information Disclosure via getBookmarkLabels
SiYuan versions before v3.7.4 contain an information disclosure vulnerability in the getBookmarkLabels endpoint that returns all bookmark labels in the workspace without publish-access filtering. Anonymous readers and publish-mode readers can obtain the complete bookmark vocabulary across the workspace, disclosing subject matter and organizational information from inaccessible documents.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
6.9
SiYuan before v3.7.4 Information Disclosure via getBookmarkLabels
SiYuan versions before v3.7.4 contain an information disclosure vulnerability in the getBookmarkLabels endpoint that returns all bookmark labels in the workspace without publish-access filtering. Anonymous readers and publish-mode readers can obtain the complete bookmark vocabulary across the workspace, disclosing subject matter and organizational information from inaccessible documents.
- Record
CVE-2026-73609- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:L/SI:N/SA:N - CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
EUVDEUVD-2026-57813
6.9
SiYuan versions before v3.7.4 contain an information disclosure vulnerability in the getBookmarkLabels endpoint that returns all bookmark labels in the workspace without publish-access filtering. Anonymous readers and publish-mode readers can obtain the complete bookmark vocabulary across the workspace, disclosing subject matter and organizational information from inaccessible documents.
- Record
EUVD-2026-57813- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:L/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-7v6h-j59w-8qfp
6.9
Duplicate Advisory: getBookmarkLabels returns every bookmark label in the workspace to anonymous readers, with no publish-access filtering
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-j4ph-9xwf-wcj4. This link is maintained to preserve external references.
Original Description
SiYuan versions before v3.7.4 contain an information disclosure vulnerability in the getBookmarkLabels endpoint that returns all bookmark labels in the workspace without publish-access filtering. Anonymous readers and publish-mode readers can obtain the complete bookmark vocabulary across the workspace, disclosing subject matter and organizational information from inaccessible documents.
- Record
GHSA-7v6h-j59w-8qfp- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:L/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-j4ph-9xwf-wcj4
5.8
SiYuan: getBookmarkLabels returns every bookmark label in the workspace to anonymous readers, with no publish-access filtering
Summary
/api/attr/getBookmarkLabels is registered with CheckAuth only and applies no filtering of any kind. It runs a scan of the entire blocks table and returns the distinct set of every bookmark label in the workspace. An anonymous reader in publish mode receives the author's complete bookmark vocabulary, regardless of whether the bookmarked blocks live in published, hidden, password-protected or forbidden documents.
The adjacent endpoint that returns bookmarks with their blocks does filter, and does so in a way that makes the intended rule explicit: it drops a label entirely when no accessible block carries it.
Details
Route. kernel/api/router.go:297 on master, :300 on the development branch:
ginServer.Handle("POST", "/api/attr/getBookmarkLabels", model.CheckAuth, getBookmarkLabels)
No CheckAdminRole, no CheckReadonly. Reachable by the publish RoleReader token and anonymously when Publish.Auth.Enable is false.
The handler (kernel/api/attr.go) is a single line:
ret.Data = model.BookmarkLabels()
which reaches kernel/model/bookmark.go:184 and then sql.QueryBookmarkLabels() at kernel/sql/block_query.go:315:
sqlStmt := "SELECT * FROM blocks WHERE ial LIKE ?" // "%bookmark=%"
// collect distinct ialAttr(block.IAL, "bookmark") into a set, sort, return
There is no notebook scoping, no path scoping, no publish-access check and no filter function anywhere on the path. Every block in the workspace carrying a bookmark attribute contributes its label to the result.
Bookmark labels are user-authored organisational text. They routinely name the thing being organised, which is the reason they are useful and also the reason they disclose.
The guarded sibling states the rule outright. getBookmark (kernel/api/router.go:190 on master, :193 on the development branch) carries the same CheckAuth-only exposure and handles the same data. It does this:
bookmark.Blocks = model.FilterBlocksByPublishAccess(c, publishAccess, bookmark.Blocks)
bookmark.Count = len(bookmark.Blocks)
if bookmark.Count > 0 {
*tempBookmarks = append(*tempBookmarks, bookmark)
}
The final condition is the significant part. The label is not merely returned with an empty block list, it is omitted from the response entirely when no accessible block carries it. The project has therefore already decided that a reader must not learn a bookmark label they have no accessible block for. getBookmarkLabels returns those same labels unconditionally, one endpoint away.
Relationship to the tag-label fix. Commit 4515fa257 ("Enforce publish access for tag labels") established that user-authored organisational labels are data the publish boundary must protect. Bookmark labels are the same class of data, drawn from the same IAL attribute store, reached through a structurally similar handler. That commit touched kernel/api/tag.go, kernel/model/publish_access.go and its test file, and nothing in attr.go or the bookmark path, so this endpoint was not covered by it.
Worth noting that the defect here is broader than the one in the tag path. The tag filter existed and checked the visible tier, so it correctly excluded forbidden documents and leaked only the password tier. getBookmarkLabels has no filter at all, so labels from forbidden documents are returned as well.
Proof of Concept
Precondition: publish mode enabled (default port 6808), anonymous when Publish.Auth.Enable is false, otherwise any publish reader account. At least one bookmarked block in a document that is not published.
POST http://127.0.0.1:6808/api/attr/getBookmarkLabels
{}
→ 200, a sorted array of every distinct bookmark label in the workspace,
including labels used only inside documents the reader has no
publish access to
No arguments are required. For contrast, the sibling endpoint returns nothing for those same labels to the same session:
POST…
- Record
GHSA-j4ph-9xwf-wcj4- CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
NVD
6.9
SiYuan versions before v3.7.4 contain an information disclosure vulnerability in the getBookmarkLabels endpoint that returns all bookmark labels in the workspace without publish-access filtering. Anonymous readers and publish-mode readers can obtain the complete bookmark vocabulary across the workspace, disclosing subject matter and organizational information from inaccessible documents.
- Record
CVE-2026-73609- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:L/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
OSVGHSA-7v6h-j59w-8qfp
6.9
Duplicate Advisory: getBookmarkLabels returns every bookmark label in the workspace to anonymous readers, with no publish-access filtering
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-j4ph-9xwf-wcj4. This link is maintained to preserve external references.
Original Description
SiYuan versions before v3.7.4 contain an information disclosure vulnerability in the getBookmarkLabels endpoint that returns all bookmark labels in the workspace without publish-access filtering. Anonymous readers and publish-mode readers can obtain the complete bookmark vocabulary across the workspace, disclosing subject matter and organizational information from inaccessible documents.
- Record
GHSA-7v6h-j59w-8qfp- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:L/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
OSVGHSA-j4ph-9xwf-wcj4
5.8
SiYuan: getBookmarkLabels returns every bookmark label in the workspace to anonymous readers, with no publish-access filtering
Summary
/api/attr/getBookmarkLabels is registered with CheckAuth only and applies no filtering of any kind. It runs a scan of the entire blocks table and returns the distinct set of every bookmark label in the workspace. An anonymous reader in publish mode receives the author's complete bookmark vocabulary, regardless of whether the bookmarked blocks live in published, hidden, password-protected or forbidden documents.
The adjacent endpoint that returns bookmarks with their blocks does filter, and does so in a way that makes the intended rule explicit: it drops a label entirely when no accessible block carries it.
Details
Route. kernel/api/router.go:297 on master, :300 on the development branch:
ginServer.Handle("POST", "/api/attr/getBookmarkLabels", model.CheckAuth, getBookmarkLabels)
No CheckAdminRole, no CheckReadonly. Reachable by the publish RoleReader token and anonymously when Publish.Auth.Enable is false.
The handler (kernel/api/attr.go) is a single line:
ret.Data = model.BookmarkLabels()
which reaches kernel/model/bookmark.go:184 and then sql.QueryBookmarkLabels() at kernel/sql/block_query.go:315:
sqlStmt := "SELECT * FROM blocks WHERE ial LIKE ?" // "%bookmark=%"
// collect distinct ialAttr(block.IAL, "bookmark") into a set, sort, return
There is no notebook scoping, no path scoping, no publish-access check and no filter function anywhere on the path. Every block in the workspace carrying a bookmark attribute contributes its label to the result.
Bookmark labels are user-authored organisational text. They routinely name the thing being organised, which is the reason they are useful and also the reason they disclose.
The guarded sibling states the rule outright. getBookmark (kernel/api/router.go:190 on master, :193 on the development branch) carries the same CheckAuth-only exposure and handles the same data. It does this:
bookmark.Blocks = model.FilterBlocksByPublishAccess(c, publishAccess, bookmark.Blocks)
bookmark.Count = len(bookmark.Blocks)
if bookmark.Count > 0 {
*tempBookmarks = append(*tempBookmarks, bookmark)
}
The final condition is the significant part. The label is not merely returned with an empty block list, it is omitted from the response entirely when no accessible block carries it. The project has therefore already decided that a reader must not learn a bookmark label they have no accessible block for. getBookmarkLabels returns those same labels unconditionally, one endpoint away.
Relationship to the tag-label fix. Commit 4515fa257 ("Enforce publish access for tag labels") established that user-authored organisational labels are data the publish boundary must protect. Bookmark labels are the same class of data, drawn from the same IAL attribute store, reached through a structurally similar handler. That commit touched kernel/api/tag.go, kernel/model/publish_access.go and its test file, and nothing in attr.go or the bookmark path, so this endpoint was not covered by it.
Worth noting that the defect here is broader than the one in the tag path. The tag filter existed and checked the visible tier, so it correctly excluded forbidden documents and leaked only the password tier. getBookmarkLabels has no filter at all, so labels from forbidden documents are returned as well.
Proof of Concept
Precondition: publish mode enabled (default port 6808), anonymous when Publish.Auth.Enable is false, otherwise any publish reader account. At least one bookmarked block in a document that is not published.
POST http://127.0.0.1:6808/api/attr/getBookmarkLabels
{}
→ 200, a sorted array of every distinct bookmark label in the workspace,
including labels used only inside documents the reader has no
publish access to
No arguments are required. For contrast, the sibling endpoint returns nothing for those same labels to the same session:
POST…
- Record
GHSA-j4ph-9xwf-wcj4- CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-862
- Updated
- 2026-11-02
OSVGO-2026-6634 No score
SiYuan: getBookmarkLabels returns every bookmark label in the workspace to anonymous readers, with no publish-access filtering in github.com/siyuan-note/siyuan/kernel
SiYuan: getBookmarkLabels returns every bookmark label in the workspace to anonymous readers, with no publish-access filtering in github.com/siyuan-note/siyuan/kernel
- Record
GO-2026-6634- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/siyuan-note/siyuan/kernelGo |
before 0.0.0-20260812083335-251596fc0de2 | 0.0.0-20260812083335-251596fc0de2 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-73609 is a medium vulnerability (CVSS 6.9) in Siyuan-note Siyuan, published August 13, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.33%, the 25th percentile. Fixed in github.com/siyuan-note/siyuan/kernel 0.0.0-20260812083335-251596fc0de2.
References
github.com/siyuan-note/siyuan/security/advisories/GHSA-j4ph-9xwf-wcj4
vulncheck.com/advisories/siyuan-before-information-disclosure-via-getbookmarklabels
nvd.nist.gov/vuln/detail/CVE-2026-73609
github.com/advisories/GHSA-7v6h-j59w-8qfp
github.com/siyuan-note/siyuan/releases/tag/v3.8.0
github.com/advisories/GHSA-j4ph-9xwf-wcj4
github.com/siyuan-note/siyuan
Left out here: the rest of 2 source descriptions. The JSON record has them.