Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹
🐹 Go
Not in CISA KEV
MEDIUM severity

CVE-2026-73606 — kernel

MEDIUM

CVE-2026-73606 is a medium-severity (CVSS 5.8) CWE-639 vulnerability in github.com/siyuan-note/siyuan/kernel. A fix is available for github.com/siyuan-note/siyuan/kernel — see the affected versions and patch details below.

SiYuan: The reference filter for getRefIDs checks visibility but not the password tier, disclosing that password-protected documents reference a given block

Also known asGO-2026-6635
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 16, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-73606.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs24th percentile — riskier than 24% of all scored CVEsHighest risk
0.00%0.28%0.55%0.83%0.2%0.3%0.3%Sep 26Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-73606 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 394,415 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐹github.com/siyuan-note/siyuan/kernel

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Summary

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

A function ten lines away in the same file does perform the full check, on the same input type.

Details

Route, identical at eef105683 (kernel/api/router.go:235) and dev a7ae96ce (:245):

ginServer.Handle("POST", "/api/block/getRefIDs", model.CheckAuth, getRefIDs)

No CheckReadonly, no CheckAdminRole.

The filter chain. getRefIDs (kernel/api/block.go:631) checks isEncryptedNotebookDeniedForPublish, calls model.GetBlockRefsInBox, then for read-only roles:

publishIgnore := model.GetInvisiblePublishAccess(publishAccess)
refDefs, originalRefBlockIDs = model.FilterRefDefsByPublishIgnore(publishIgnore, refDefs)

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:

for id, bt := range bts {
    if CheckPathAccessableByPublishIgnore(bt.BoxID, bt.Path, publishIgnore) {
        ret[id] = bt
    }
}

Inside that helper, CheckPublishAuthCookie, GetPathPasswordByPublishAccess, checkBlockTreeAccessableByPublishAccess and password all appear zero times.

The complete check exists in the same file. kernel/model/publish_access.go:431:

func checkBlockTreeAccessableByPublishAccess(c *gin.Context, publishAccess PublishAccess, bt *treenode.BlockTree) bool {
    if bt == nil || IsEncryptedBoxDeniedByPublishAccess(bt.BoxID) {
        return false
    }
    publishIgnore := filterDisablePublishAccess(publishAccess)
    passwordID, password := GetPathPasswordByPublishAccess(bt.BoxID, bt.Path, publishAccess)
    return CheckPathAccessableByPublishIgnore(bt.BoxID, bt.Path, publishIgnore) &&
           (password == "" || CheckPublishAuthCookie(c, passwordID, password))
}

Same package, same file, same *treenode.BlockTree input. One takes the context and evaluates the password; the other does not receive it and structurally cannot.

Route-level contrast. The adjacent getChildBlocks and getTailChildBlocks both carry model.CheckAdminRole.

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.

Proof of Concept

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

Tier of the referring documentAnonymous result
Publicreference returned (baseline)
Password-protectedreference still returned
Hidden[], filtered
Forbidden[], filtered

The hidden and forbidden rows confirm the filter runs and works. The password-protected row is the defect.

Impact

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

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

Confidentiality only.

Suggested fix

Thread *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.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/siyuan-note/siyuan/kernelall versions0.0.0-20260812083335-251596fc0de2go get github.com/siyuan-note/siyuan/kernel@v0.0.0-20260812083335-251596fc0de2

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/siyuan-note/siyuan/kernel, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update github.com/siyuan-note/siyuan/kernel to 0.0.0-20260812083335-251596fc0de2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-73606 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

Frequently Asked Questions

### Summary `/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. A function ten lines away in the same file does perform the full check, on the same input type. ### Details **Route,** identical at `eef105683` (`kernel/api/router.go:235`) and dev `a7ae96ce` (`:245`): ```go ginS
O3 Security · Impact-Aware SCA

Is CVE-2026-73606 in your dependencies?

Find it across Go, including transitive dependencies.

CVE-2026-73606: kernel — Fix Available