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

CVE-2026-72789 — kernel

HIGHFix: siyuan-note/siyuan@a25c2dd

CVE-2026-72789 is a high-severity (CVSS 8.6) CWE-862 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 publish-access gate treats encrypted notebooks as publicly accessible by default, allowing anonymous readers to retrieve fully decrypted document content while a notebook is unlocked

Also known asGO-2026-6434
Published
Sep 8, 2026
Updated
Sep 10, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 26, 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-72789.

EPSS Exploitation Probability

via FIRST.org ↗
0.5%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs41th percentile — riskier than 41% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

CVE-2026-72789 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 379,842 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

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

CVE: This vulnerability corresponds to CVE-2026-72789.

Summary

publishAccess.json is an opt-out list. The publish gate returns accessible for anything not explicitly listed in it. Encrypted notebooks are never written into that file, because only the administrator-gated setPublishAccess writes it and no part of the encryption subsystem does. Consequently every encrypted notebook is publish-accessible as far as the gate is concerned.

While an encrypted notebook is unlocked, an anonymous reader in publish mode can list it, enumerate its documents, and retrieve their fully decrypted content. No key material, no password, and no cracking is involved. The kernel decrypts the data and serves it because the authorization layer never asks whether the notebook is encrypted.

This is reported as a defect in the gate rather than in any individual handler. Endpoints that were previously reviewed and found to apply the correct checks do apply them. The checks return true.

Details

The gate defaults to accessible. CheckPathAccessableByPublishIgnore(box, path, ignore) iterates the ignore list and returns false only on a match:

for _, item := range publishIgnore {
    if item.ID == box || strings.Contains(path, item.ID) {
        return false
    }
}
return true   // unlisted means accessible

Encrypted notebooks are never listed. publishAccess.json is written only by setPublishAccess (kernel/api/router.go:169), which carries CheckAdminRole and CheckReadonly. Nothing in crypto.go, encrypted_ops.go or notebook_crypto.go writes to it. An administrator would have to manually add each encrypted notebook to the ignore list to protect it, and nothing in the product prompts or documents that.

Neither core gate rejects them. On both eef105683 and v3.7.4-alpha.1:

func checkBlockTreeAccessableByPublishAccess(...) bool {
    return CheckPathAccessableByPublishIgnore(bt.BoxID, bt.Path, publishIgnore) &&
           (password == "" || CheckPublishAuthCookie(c, passwordID, password))
}

For an encrypted notebook the first term is true because it is unlisted, and the second is true because encrypted notebooks carry no publish password. The conjunction returns true.

IsEncryptedBox does not appear in kernel/model/publish_access.go at all on master. On the development branch it appears once, inside parseAttributeViewForPublishAccess, where it routes into encrypted boxes rather than excluding them. The publish authorization layer has no concept of an encrypted notebook.

The chain. Verified on the development branch, which is the harder target because the block-metadata, attribute-view, path-resolution and encrypted-notebook-status fixes have all landed there.

  1. lsNotebooks calls ListNotebooks(), which includes encrypted notebooks and reports Encrypted: boxConf.Encrypted without filtering on it. The reader filter skips only notebooks that are Closed or publish-invisible. An unlocked encrypted notebook is neither, so it is returned to an anonymous reader together with its identifier.
  2. listDocsByPath{notebook: <encrypted box id>, path: "/"} applies only CheckPathAccessableByPublishIgnore, which passes, returning the document identifiers and titles inside the encrypted notebook.
  3. getDoc routes to GetDocInBox(...), after which FilterContentByPublishAccess(...) returns the content unmodified because the box is unlisted. The response is the fully decrypted document. getBlockKramdown reaches GetBlockKramdownInBox for the same result in Markdown.

Handlers reach the decrypted store through encryptedNotebookFromArg(arg) on a client-supplied notebook argument. This function predates the current release and is not a recent addition.

The precondition is the unlock window. GetBlockTreeInBox returns nil while a notebook is locked, treating it as nonexistent, and non-nil once unlocked. So the exposure is bounded to the period during which the legitimate user has the notebook open, which is precisely the period in which they are working in it. No action by the attacker triggers or extends that window, but no unusual condition is required either.

On endpoints previously assessed as correctly gated. getBlockDOM and getBlockKramdown apply password and visibility checks. exportPreview applies FilterContentByPublishAccess. Those assessments are accurate and this report does not contradict them. The checks execute and return true, because the visibility term resolves to accessible for an unlisted box and the password term is vacuous for a notebook that has no publish password. Patching any individual handler would not change that result.

Proof of Concept

Precondition: publish mode enabled (default port 6808), anonymous when Publish.Auth.Enable is false, otherwise any publish reader account. An encrypted notebook that is currently unlocked by the legitimate user.

Step 1, obtain the encrypted notebook's identifier:

POST http://127.0.0.1:6808/api/notebook/lsNotebooks
{}

→ 200. The list includes the encrypted notebook, with encrypted: true and its id.

Step 2, enumerate its documents:

POST http://127.0.0.1:6808/api/filetree/listDocsByPath
{"notebook":"<encrypted box id>","path":"/"}

→ 200, document identifiers and titles from inside the encrypted notebook

Step 3, retrieve decrypted content:

POST http://127.0.0.1:6808/api/filetree/getDoc
{"id":"<document id from step 2>"}

→ 200, the fully decrypted document

getBlockKramdown returns the same content as decrypted Markdown. Repeating step 3 while the notebook is locked returns not-found, which confirms the unlock window is the only thing standing between an anonymous reader and the plaintext.

Impact

The confidentiality guarantee of the encrypted-notebook feature is defeated against a remote, unauthenticated attacker for as long as the notebook is unlocked. A user who encrypts a notebook is expressing that its contents should be protected beyond the ordinary publish boundary. The publish gate does not recognise that intent, and instead treats the notebook as publicly readable because nobody added it to an opt-out list that the encryption feature does not write to.

The exposure is full document content rather than metadata, and it applies to every document in the notebook. It requires no key material, no password, no offline work and no interaction with the encryption subsystem at all.

Suggested fix

Fail closed on encryption, independently of publishAccess.json:

if IsEncryptedBox(bt.BoxID) {
    return false
}

in both checkBlockTreeAccessableByPublishAccess and CheckBlockTreeMetadataAccessableByPublishAccess, and exclude encrypted notebooks from lsNotebooks and listDocsByPath for read-only roles.

The broader point is the default. An opt-out authorization list means every future notebook type, storage backend or content class is publicly accessible until somebody remembers to add it. Encrypted notebooks are the case where that default is most clearly wrong, but they are unlikely to be the only one.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/siyuan-note/siyuan/kernelall versions0.0.0-20260726020813-a25c2dd06aaego get github.com/siyuan-note/siyuan/kernel@v0.0.0-20260726020813-a25c2dd06aae

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-20260726020813-a25c2dd06aae or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-72789 is resolved across your whole dependency graph.

  3. Workarounds

    Put an independent control in front of the weakness: restrict the affected endpoint or interface to trusted networks, require an additional authentication factor or proxy-level check, and invalidate existing sessions and credentials in case the flaw has already been used.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-72789 can be triaged on real exposure rather than presence alone.

Tailored to CVE-2026-72789. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

**CVE:** This vulnerability corresponds to [CVE-2026-72789](https://nvd.nist.gov/vuln/detail/CVE-2026-72789). ### Summary `publishAccess.json` is an opt-out list. The publish gate returns *accessible* for anything not explicitly listed in it. Encrypted notebooks are never written into that file, because only the administrator-gated `setPublishAccess` writes it and no part of the encryption subsystem does. Consequently every encrypted notebook is publish-accessible as far as the gate is concerned. While an encrypted notebook is unlocked, an anonymous reader in publish mode can list it, enume
O3 Security · Impact-Aware SCA

Is CVE-2026-72789 in your dependencies?

O3 Security finds CVE-2026-72789 across Go dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

CVE-2026-72789: kernel (High 8.6) | O3 Security