{"id":"CVE-2026-73609","revision":null,"records":[{"revision":"01375b82343a4a769f9301a5d4f17cd8","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-73609","aliases":[],"title":"SiYuan before v3.7.4 Information Disclosure via getBookmarkLabels","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.","state":0,"publishedAt":"2026-08-13T11:28:13.793+00:00","modifiedAt":"2026-08-14T20:18:31.189+00:00","affected":[{"ecosystem":"Vendor product","name":"siyuan","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"siyuan-note\",\n                    \"product\": \"siyuan\",\n                    \"defaultStatus\": \"unaffected\",\n                    \"packageURL\": \"pkg:golang/github.com/siyuan-note/siyuan/kernel\",\n                    \"versions\": [\n                        {\n                            \"version\": \"0\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"semver\",\n                            \"lessThan\": \"3.7.4\"\n                        },\n                        {\n                            \"version\": \"3.7.4\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"semver\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"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","score":6.9,"severity":"MEDIUM"},{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N","score":5.8,"severity":"MEDIUM"}],"references":["https://github.com/siyuan-note/siyuan/security/advisories/GHSA-j4ph-9xwf-wcj4","https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-getbookmarklabels"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-73609","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-73609","identifiers":["CVE-2026-73609"]},"retained":false,"historicalAffected":[]},{"revision":"1831089b687b46f98c4e01117d785879","observedAt":"2026-10-25T15:19:09.409+00:00","statement":{"source":"nvd","id":"CVE-2026-73609","aliases":[],"title":"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 c…","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.","state":0,"publishedAt":"2026-08-13T12:17:25.463+00:00","modifiedAt":"2026-10-24T15:10:00.19+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · disclosure@vulncheck.com · Secondary","vector":"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","score":6.9,"severity":"MEDIUM"},{"system":"CVSS 3.1 · disclosure@vulncheck.com · Secondary","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N","score":5.8,"severity":"MEDIUM"}],"references":["https://github.com/siyuan-note/siyuan/security/advisories/GHSA-j4ph-9xwf-wcj4","https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-getbookmarklabels"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-73609","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-862"],"productCriteria":[],"sourceDates":{"published":"2026-08-13T12:17:25.463","lastModified":"2026-10-24T15:10:00.190"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-73609","identifiers":["CVE-2026-73609"]},"retained":false,"historicalAffected":[]},{"revision":"bdcc0369f2c1481e836af712240039a5","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GHSA-j4ph-9xwf-wcj4","aliases":["CVE-2026-73609","GO-2026-6634"],"title":"SiYuan: getBookmarkLabels returns every bookmark label in the workspace to anonymous readers, with no publish-access filtering","description":"### Summary\n\n`/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.\n\nThe 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.\n\n### Details\n\n**Route.** `kernel/api/router.go:297` on master, `:300` on the development branch:\n\n```go\nginServer.Handle(\"POST\", \"/api/attr/getBookmarkLabels\", model.CheckAuth, getBookmarkLabels)\n```\n\nNo `CheckAdminRole`, no `CheckReadonly`. Reachable by the publish `RoleReader` token and anonymously when `Publish.Auth.Enable` is `false`.\n\n**The handler** (`kernel/api/attr.go`) is a single line:\n\n```go\nret.Data = model.BookmarkLabels()\n```\n\nwhich reaches `kernel/model/bookmark.go:184` and then `sql.QueryBookmarkLabels()` at `kernel/sql/block_query.go:315`:\n\n```go\nsqlStmt := \"SELECT * FROM blocks WHERE ial LIKE ?\"   // \"%bookmark=%\"\n// collect distinct ialAttr(block.IAL, \"bookmark\") into a set, sort, return\n```\n\nThere 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.\n\nBookmark 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.\n\n**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:\n\n```go\nbookmark.Blocks = model.FilterBlocksByPublishAccess(c, publishAccess, bookmark.Blocks)\nbookmark.Count  = len(bookmark.Blocks)\nif bookmark.Count > 0 {\n    *tempBookmarks = append(*tempBookmarks, bookmark)\n}\n```\n\nThe 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.\n\n**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.\n\nWorth 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.\n\n### Proof of Concept\n\nPrecondition: 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.\n\n```\nPOST http://127.0.0.1:6808/api/attr/getBookmarkLabels\n{}\n\n→ 200, a sorted array of every distinct bookmark label in the workspace,\n       including labels used only inside documents the reader has no\n       publish access to\n```\n\nNo arguments are required. For contrast, the sibling endpoint returns nothing for those same labels to the same session:\n\n```\nPOST http://127.0.0.1:6808/api/attr/getBookmark\n{}\n\n→ 200, labels omitted entirely where no accessible block carries them\n```\n\nOne endpoint withholds the label, the other returns it.\n\n### Impact\n\nAn anonymous reader in publish mode, or any publish `RoleReader`, obtains the author's complete bookmark vocabulary across the workspace. Bookmark labels are free text chosen to describe what is being organised, so the set discloses subject matter, project names, personal and organisational names, and the general shape of what the author is working on, including material in documents that are hidden, password-protected or explicitly forbidden to readers.\n\nScoped honestly: this returns labels only. No block identifiers, document identifiers or content are included, so it does not extend into the identifier-to-content resolution paths. Confidentiality only, with no integrity or availability impact.\n\n### Suggested fix\n\nMirror `getBookmark`. For read-only roles, build the label set from blocks that have passed `FilterBlocksByPublishAccess`, and emit a label only if at least one surviving block carries it. That is the rule the sibling endpoint already implements, applied to the same data.","state":0,"publishedAt":"2026-10-01T16:23:37+00:00","modifiedAt":"2026-10-07T17:56:02.3314484+00:00","affected":[{"ecosystem":"Go","name":"github.com/siyuan-note/siyuan/kernel","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"0.0.0-20260812083335-251596fc0de2"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/siyuan-note/siyuan/security/advisories/GHSA-j4ph-9xwf-wcj4","https://nvd.nist.gov/vuln/detail/CVE-2026-73609","https://github.com/siyuan-note/siyuan","https://github.com/siyuan-note/siyuan/releases/tag/v3.8.0","https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-getbookmarklabels"],"sourceUrl":"https://github.com/advisories/GHSA-j4ph-9xwf-wcj4","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-j4ph-9xwf-wcj4","identifiers":["GHSA-j4ph-9xwf-wcj4","CVE-2026-73609","GO-2026-6634"]},"retained":false,"historicalAffected":[]},{"revision":"9b3157a5ddd843f2b1668d0634ff6ac3","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GO-2026-6634","aliases":["CVE-2026-73609","GHSA-j4ph-9xwf-wcj4"],"title":"SiYuan: getBookmarkLabels returns every bookmark label in the workspace to anonymous readers, with no publish-access filtering in github.com/siyuan-note/siyuan/kernel","description":"SiYuan: getBookmarkLabels returns every bookmark label in the workspace to anonymous readers, with no publish-access filtering in github.com/siyuan-note/siyuan/kernel","state":0,"publishedAt":"2026-10-07T14:09:59+00:00","modifiedAt":"2026-10-07T17:45:13.4717574+00:00","affected":[{"ecosystem":"Go","name":"github.com/siyuan-note/siyuan/kernel","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"0.0.0-20260812083335-251596fc0de2"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[],"references":["https://github.com/siyuan-note/siyuan/security/advisories/GHSA-j4ph-9xwf-wcj4","https://nvd.nist.gov/vuln/detail/CVE-2026-73609","https://github.com/siyuan-note/siyuan/releases/tag/v3.8.0","https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-getbookmarklabels"],"sourceUrl":"https://osv.dev/vulnerability/GO-2026-6634","license":"OSV · upstream source license applies","key":"osv:GO-2026-6634","identifiers":["GO-2026-6634","CVE-2026-73609","GHSA-j4ph-9xwf-wcj4"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-10-25T23:02:08.9235896+00:00","complete":true,"records":1756,"lastAttemptAt":"2026-10-25T23:02:08.9235896+00:00","lastSuccessAt":"2026-10-25T23:02:09.0869487+00:00","error":null,"lastVerifiedAt":"2026-10-25T23:02:09.0869513+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-1a687ad2a0b90150aa7d97c9f39e63de695ae2db23e31ebc28df1492c461b23c-5e0a45ae0cf63c80268dd44eaeb20879d480eba4da3306bde3dcd925fa4c114f","complete":true,"records":414047,"lastAttemptAt":"2026-10-25T23:02:08.5196863+00:00","lastSuccessAt":"2026-10-25T23:02:08.4495153+00:00","error":null,"lastVerifiedAt":"2026-10-25T23:02:08.5196863+00:00","snapshotPublishedAt":"2026-10-25T22:26:55+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-43321610382942b8ad8c85917eab1546","complete":false,"records":4735,"lastAttemptAt":"2026-10-25T23:02:11.7890287+00:00","lastSuccessAt":"2026-10-24T23:18:49.862+00:00","error":"InvalidDataException","lastVerifiedAt":"2026-10-24T23:18:49.862+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":4764,"expectedIdentifiers":13474},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-10-25T23:02:08.9235896+00:00","complete":true,"records":1093,"lastAttemptAt":"2026-10-25T23:02:08.9235896+00:00","lastSuccessAt":"2026-10-25T23:02:09.087647+00:00","error":null,"lastVerifiedAt":"2026-10-25T23:02:09.08765+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-204a3fb93a00487e8f7f36db01dc851d","complete":true,"records":13413,"lastAttemptAt":"2026-10-25T23:02:09.6218557+00:00","lastSuccessAt":"2026-10-25T16:19:28.681+00:00","error":null,"lastVerifiedAt":"2026-10-25T16:19:28.681+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13474,"expectedIdentifiers":13474},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-2375a4e597279abf92e8747e140fe8da9d421877cd49cae3ac69a2cb78469b2c","complete":true,"records":9779,"lastAttemptAt":"2026-10-25T23:02:08.8808579+00:00","lastSuccessAt":"2026-10-24T13:19:53.1346702+00:00","error":null,"lastVerifiedAt":"2026-10-25T23:02:08.8808579+00:00","snapshotPublishedAt":"2026-10-24T03:03:12+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-16ad89dfea13ab9e9b0108e63a759d63bd4559cc68b58491107d62ee35bbbaf2","complete":true,"records":1965,"lastAttemptAt":"2026-10-25T23:02:08.6737644+00:00","lastSuccessAt":"2026-10-23T16:01:26.4487605+00:00","error":null,"lastVerifiedAt":"2026-10-25T23:02:08.6737644+00:00","snapshotPublishedAt":"2026-10-21T12:18:07+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-7da67a15aa6e56a0e3081a7646dc74d537e6ef974afc593c2b1794ed01970648","complete":true,"records":2969,"lastAttemptAt":"2026-10-25T23:02:08.8933341+00:00","lastSuccessAt":"2026-10-24T13:19:59.1145547+00:00","error":null,"lastVerifiedAt":"2026-10-25T23:02:08.8933341+00:00","snapshotPublishedAt":"2026-10-24T08:47:51+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-11236ada05a0588e51df37636716526867f73fb127392c49680b6f8561496a99","complete":true,"records":230781,"lastAttemptAt":"2026-10-25T23:02:08.7805888+00:00","lastSuccessAt":"2026-10-25T22:04:07.173333+00:00","error":null,"lastVerifiedAt":"2026-10-25T23:02:08.7805888+00:00","snapshotPublishedAt":"2026-10-25T21:33:06+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null}]}