{"schema":"threatline.record/2","record":{"id":"CVE-2026-73606","aliases":["GHSA-vg99-7gj7-2fr5","GO-2026-6635"],"summary":"SiYuan: The reference filter for getRefIDs checks visibility but not the password tier, disclosing that password-protected documents reference a given block","details":"### Summary\n\n`/api/block/getRefIDs` filters its results for reader roles through a helper that checks only the visibility tiers. The password tier is not checked, because the helper does not receive the request context and therefore cannot evaluate the publish auth cookie. A reader who has not entered a document's publish password learns that the document references a given block.\n\nA function ten lines away in the same file does perform the full check, on the same input type.\n\n### Details\n\n**Route,** identical at `eef105683` (`kernel/api/router.go:235`) and dev `a7ae96ce` (`:245`):\n\n```go\nginServer.Handle(\"POST\", \"/api/block/getRefIDs\", model.CheckAuth, getRefIDs)\n```\n\nNo `CheckReadonly`, no `CheckAdminRole`.\n\n**The filter chain.** `getRefIDs` (`kernel/api/block.go:631`) checks `isEncryptedNotebookDeniedForPublish`, calls `model.GetBlockRefsInBox`, then for read-only roles:\n\n```go\npublishIgnore := model.GetInvisiblePublishAccess(publishAccess)\nrefDefs, originalRefBlockIDs = model.FilterRefDefsByPublishIgnore(publishIgnore, refDefs)\n```\n\n`FilterRefDefsByPublishIgnore` (`kernel/model/publish_access.go:1324`) collects the reference and definition identifiers, resolves their block trees, and delegates the decision to `FilterBlockTreesByPublishIgnore` (`:1314`), whose entire body is:\n\n```go\nfor id, bt := range bts {\n    if CheckPathAccessableByPublishIgnore(bt.BoxID, bt.Path, publishIgnore) {\n        ret[id] = bt\n    }\n}\n```\n\nInside that helper, `CheckPublishAuthCookie`, `GetPathPasswordByPublishAccess`, `checkBlockTreeAccessableByPublishAccess` and `password` all appear zero times.\n\n**The complete check exists in the same file.** `kernel/model/publish_access.go:431`:\n\n```go\nfunc checkBlockTreeAccessableByPublishAccess(c *gin.Context, publishAccess PublishAccess, bt *treenode.BlockTree) bool {\n    if bt == nil || IsEncryptedBoxDeniedByPublishAccess(bt.BoxID) {\n        return false\n    }\n    publishIgnore := filterDisablePublishAccess(publishAccess)\n    passwordID, password := GetPathPasswordByPublishAccess(bt.BoxID, bt.Path, publishAccess)\n    return CheckPathAccessableByPublishIgnore(bt.BoxID, bt.Path, publishIgnore) &&\n           (password == \"\" || CheckPublishAuthCookie(c, passwordID, password))\n}\n```\n\nSame package, same file, same `*treenode.BlockTree` input. One takes the context and evaluates the password; the other does not receive it and structurally cannot.\n\n**Route-level contrast.** The adjacent `getChildBlocks` and `getTailChildBlocks` both carry `model.CheckAdminRole`.\n\n**Note on a prior assessment.** `getRefIDs` has been described as correctly filtered because it calls a publish-access filter. It does. The filter it calls covers the visibility tiers only.\n\n### Proof of Concept\n\nKernel 3.7.2, publish mode on port 6808, `Publish.Auth.Enable` false, anonymous client. A public document referenced from a second document whose publish tier was changed between runs. `getRefIDs` was called anonymously each time.\n\n| Tier of the referring document | Anonymous result |\n|---|---|\n| Public | reference returned (baseline) |\n| Password-protected | **reference still returned** |\n| Hidden | `[]`, filtered |\n| Forbidden | `[]`, filtered |\n\nThe hidden and forbidden rows confirm the filter runs and works. The password-protected row is the defect.\n\n### Impact\n\nAn anonymous reader in publish mode, or any publish `RoleReader`, learns that a password-protected document contains a reference to a given block, without entering that document's password, and receives the block identifiers involved.\n\nScoped precisely: the response carries identifiers only. `type RefDefs { RefID string; DefIDs []string }`, returned alongside `originalRefBlockIDs`, a map of identifier to identifier. There is no reference text, title or content. The disclosure is the existence of a relationship, plus identifiers usable as input to other endpoints.\n\nConfidentiality only.\n\n### Suggested fix\n\nThread `*gin.Context` into `FilterRefDefsByPublishIgnore` and `FilterBlockTreesByPublishIgnore`, and use `checkBlockTreeAccessableByPublishAccess` in place of the bare `CheckPathAccessableByPublishIgnore` call, so the password tier and the encrypted-box check are both applied.","categories":["Libraries & packages"],"product":"github.com/siyuan-note/siyuan/kernel","vendor":"siyuan-note","ecosystem":"go","affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-vg99-7gj7-2fr5","source_modified_at":"2026-10-01T16:29:36Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"github.com/siyuan-note/siyuan/kernel"},"range":"< 0.0.0-20260812083335-251596fc0de2"},{"source":"CVE List","source_url":"https://www.cve.org/CVERecord?id=CVE-2026-73606","source_modified_at":"2026-08-14T16:52:32.090Z","fetched_at":"2026-10-23T18:45:31.882637Z","product":"siyuan","vendor":"siyuan-note","versions":[{"version":"0","status":"affected","versionType":"semver","lessThan":"3.7.4"},{"version":"3.7.4","status":"unaffected","versionType":"semver"}],"defaultStatus":"unaffected"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-vg99-7gj7-2fr5","source_modified_at":"2026-10-07T17:55:43.026477085Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"Go","name":"github.com/siyuan-note/siyuan/kernel","purl":"pkg:golang/github.com/siyuan-note/siyuan/kernel"},"ranges":[{"events":[{"introduced":"0"},{"fixed":"0.0.0-20260812083335-251596fc0de2"}],"type":"SEMVER"}],"versions":[]}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-vg99-7gj7-2fr5","source_modified_at":"2026-10-01T16:29:36Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"github.com/siyuan-note/siyuan/kernel"},"version":"0.0.0-20260812083335-251596fc0de2"},{"source":"CVE List","source_url":"https://www.cve.org/CVERecord?id=CVE-2026-73606","source_modified_at":"2026-08-14T16:52:32.090Z","fetched_at":"2026-10-23T18:45:31.882637Z","package":{"name":"siyuan","ecosystem":null},"version":"3.7.4","basis":"first unaffected version stated in the CVE record"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-vg99-7gj7-2fr5","source_modified_at":"2026-10-07T17:55:43.026477085Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"Go","name":"github.com/siyuan-note/siyuan/kernel","purl":"pkg:golang/github.com/siyuan-note/siyuan/kernel"},"version":"0.0.0-20260812083335-251596fc0de2"}],"cvss":5.8,"severity":"Medium","kev":{"listed":false},"epss":{"probability":0.00325,"percentile":0.24331,"score_date":"2026-10-23"},"published_at":"2026-08-13T11:28:11.481Z","modified_at":"2026-10-07T17:55:43.026477085Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/advisories/GHSA-vg99-7gj7-2fr5","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-01T16:29:36Z"},{"source":"CVE List","url":"https://www.cve.org/CVERecord?id=CVE-2026-73606","fetched_at":"2026-10-23T18:45:31.882637Z","source_modified_at":"2026-08-14T16:52:32.090Z"},{"source":"OSV","url":"https://osv.dev/vulnerability/GHSA-vg99-7gj7-2fr5","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-07T17:55:43.026477085Z"},{"source":"EPSS","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-73606","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-23"}],"sources":["GitHub Advisory Database","CVE List","OSV","EPSS"],"references":[{"source":"CVE List","url":"https://github.com/siyuan-note/siyuan/security/advisories/GHSA-vg99-7gj7-2fr5","tags":["exploit"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-73606","source":"GitHub Advisory Database"},{"url":"https://github.com/siyuan-note/siyuan/releases/tag/v3.8.0","source":"GitHub Advisory Database"},{"source":"CVE List","url":"https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-getrefids","tags":["third-party-advisory"]},{"url":"https://github.com/advisories/GHSA-vg99-7gj7-2fr5","source":"GitHub Advisory Database"}],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"cve_state":"PUBLISHED","ssvc":{"exploitation":"poc","automatable":"yes","technical_impact":"partial","assessed_at":"2026-08-13T12:47:23.534766Z"},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":"ecosystem","confidence":"heuristic","reviewed":false},"change_timestamp":"2026-10-07T17:55:43.026477085Z","content_hash":"020a166dd8e8fd08de39a21ccc33cc68128b21dd097f4ac0699261b0cbc9bae4"}}
