Skip to content

GHSA-74pj-6g7r-j55c CVE-2026-72790 GO-2026-6431

SiYuan: Notebook name, document count, size and timestamps are returned for any notebook, including notebooks hidden from readers, by /api/notebook/getNotebookInfo

Medium Go
Severity
6.9 / 10
Medium · CVSS 4.0
Exploit chance (EPSS)
0.33%
Chance of exploitation in the next 30 days. Higher than 25.58% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-862 Missing Authorization
Fix
0.0.0-20260726005141-9edb321eb451
Upgrade github.com/siyuan-note/siyuan/kernel to this version or later

Description

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

Relationship to GHSA-8x84-r2ff-h8pq (please read first)

getNotebookInfo is named in the earlier advisory GHSA-8x84-r2ff-h8pq, in its remediation section, which asked for reader filtering on both getNotebookConf and getNotebookInfo. Commit 3bc014c7d applied that filtering to getNotebookConf only.

That advisory grouped getNotebookInfo under BoxCrypt, and getNotebookInfo never returns BoxCrypt. Anyone checking the handler for key material would correctly find none and move on. This report corrects that characterisation and states what the handler actually discloses, which is notebook metadata rather than key material. If you would prefer this tracked as a follow-up on the original advisory rather than separately, that is entirely reasonable.

Summary

/api/notebook/getNotebookInfo is registered with CheckAuth only and applies no authorization check of any kind. Given a notebook identifier, it returns that notebook's author-written name, document count, total size and creation and modification timestamps. It does so for every notebook the server has loaded, including notebooks that lsNotebooks deliberately withholds from readers because they are closed or not publish-visible.

Details

Item Detail
Route kernel/api/router.go:123 POST /api/notebook/getNotebookInfo → model.CheckAuth → getNotebookInfo
Middleware CheckAuth only, no CheckReadonly, no CheckAdminRole
Guard in handler None. IsReadOnlyRoleContext, publishAccess, Visible and Closed all return zero matches
Exposed BoxInfo{ID, Name, DocCount, Size, HSize, Mtime, CTime, HMtime, HCtime}
Affected refs eef105683 (v3.7.3, master HEAD) and v3.7.4-alpha.1, handler identical on both

The handler. It validates boxID against the ID pattern, calls box := model.Conf.Box(boxID), returns a not-found response if that is nil, and otherwise returns box.GetInfo() unmodified. GetInfo() (kernel/model/box.go:470) walks the notebook's files and returns the metadata listed above. There is no ownership check and no publish-access check anywhere on the path.

The nil branch is also a minor existence oracle: a valid-format identifier that names no loaded notebook is distinguishable from one that does.

Guarded sibling. lsNotebooks, the notebook lister, is also reader-reachable and does filter. For read-only roles it skips any notebook where notebook.Closed holds, and skips any notebook whose publish-access entry has !item.Visible. The codebase therefore intends closed and non-published notebooks to be invisible to readers. getNotebookInfo returns their name and statistics to any reader who supplies the identifier.

Precedent. GHSA-f2rw-w22v-54vh restricted getEncryptedNotebookStatus, which disclosed encrypted-notebook names and lock state, to administrators. getNotebookInfo is the non-encrypted analogue, disclosing regular notebook names and statistics including for notebooks outside the reader's publish scope, and was not restricted.

Reachability, stated precisely, because it differs by branch.

On v3.7.3 a reader can obtain the identifier of a notebook they cannot see, by chaining two endpoints that are currently ungated on that branch. getBlockDefIDsByRefText returns block and document identifiers workspace-wide, including from hidden notebooks. getPathByID then returns the owning notebook identifier for any such block, in its notebook field. getFullHPathByID additionally discloses the notebook name directly. The chain requires no special conditions beyond a reference text that occurs somewhere in the workspace.

On the development branch those sources are already closed. getPathByID now gates through CheckBlockIdMetadataAccessableByPublishAccessInBox, getIDsByHPath through filterFileTreeBlockIDsByPublishDiscoverability, and getBlockDefIDsByRefText and getFullHPathByID are likewise gated. Notebook identifiers are a fourteen-digit timestamp plus seven random characters, and Conf.Box(boxID) returns non-nil only for loaded notebooks, so guessing is not practical. A reader-reachable route on the development branch that yields the identifier of a hidden notebook was not found.

So on the development branch this is defence in depth rather than a live path. It is reported because the handler itself remains unguarded on both branches, and because closing it removes any dependence on those identifier sources staying gated in future.

Proof of Concept

Precondition: publish mode enabled (default port 6808), anonymous when Publish.Auth.Enable is false, otherwise any publish reader account. A notebook that is closed or not publish-visible. Steps 1 and 2 apply to v3.7.3; on the development branch, start at step 3 with a known identifier.

Step 1, obtain block identifiers workspace-wide:

POST http://127.0.0.1:6808/api/block/getBlockDefIDsByRefText
{"anchor":"<a word likely to occur anywhere in the workspace>"}

→ 200, block and document identifiers including ones inside hidden notebooks

Step 2, resolve one to its owning notebook:

POST http://127.0.0.1:6808/api/filetree/getPathByID
{"id":"<identifier from step 1>"}

→ 200, the notebook field carries the hidden notebook's boxID

Step 3, read the notebook's metadata:

POST http://127.0.0.1:6808/api/notebook/getNotebookInfo
{"notebook":"<boxID from step 2>"}

→ 200, returns name, docCount, size, hSize, mtime, ctime, hMtime, hCtime
   for a notebook that lsNotebooks does not return to this same session

The differential is the point: call lsNotebooks with the same session and confirm the notebook is absent from the list, then call getNotebookInfo and receive its name and statistics.

Impact

An anonymous reader in publish mode, or any publish RoleReader, can read the author-written name, document count, total size and activity timestamps of notebooks that are closed or not published, which are exactly the notebooks the notebook lister withholds from them. Notebook names are free text chosen by the author and routinely describe their contents. Document count and size indicate scale, and the modification timestamp reveals recent activity in a workspace area the reader has no access to. Confidentiality only, with no integrity or availability impact, and no document content is disclosed.

Suggested fix

Apply the same filtering lsNotebooks already performs. When IsReadOnlyRoleContext(c) holds, return the not-found response unless the notebook is publish-visible and not closed, before calling GetInfo(). This is the reader filtering the earlier advisory's remediation section requested for this handler.

Affected versions

Go

PackageVulnerableFixed in
github.com/siyuan-note/siyuan/kernel
< 0.0.0-20260726005141-9edb321eb451
0.0.0-20260726005141-9edb321eb451

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

github.com/siyuan-note/siyuan/kernel Go → 0.0.0-20260726005141-9edb321eb451

go
go get github.com/siyuan-note/siyuan/kernel@v0.0.0-20260726005141-9edb321eb451 && go mod tidy

Severity breakdown

CVSS 4.0 6.9

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

Attack vector
Network
Attack complexity
Low
Attack requirements
None
Privileges required
None
User interaction
None
Confidentiality (vulnerable system)
Low
Integrity (vulnerable system)
None
Availability (vulnerable system)
None
Confidentiality (subsequent systems)
Low
Integrity (subsequent systems)
None
Availability (subsequent systems)
None
Exploit maturity
Not defined
Scope
X

CVSS 3.1 5.8

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Changed
Confidentiality
Low
Integrity
None
Availability
None

Weakness

CWE-862: Missing Authorization

The product does not perform an authorization check when an actor attempts to access a resource or perform an action.

How to prevent it
  • Architecture and Design: Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries. Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
  • Architecture and Design: Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].
  • Architecture and Design: Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid. For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
  • Architecture and Design: For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page. One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
  • System Configuration, Installation: Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-xp3q-r38w-vgqm
SiYuan: The publish filter for local storage returns the administrator's entire storage map with only three keys sanitized
Medium Also affects github.com/siyuan-note/siyuan/kernel
GHSA-9cqf-hhrq-7v45
SiYuan: getAttributeViewSearchTarget returns database row content to anonymous readers with no publish-access check, reopening the class closed one day earlier at the adjacent route
High Also affects github.com/siyuan-note/siyuan/kernel
GHSA-57v5-wqx3-cgj4
SiYuan: Database view structure (all view names, layout types and per-field visibility) is returned to anonymous readers by /api/av/getAttributeViewFieldViews
Medium Also affects github.com/siyuan-note/siyuan/kernel
GHSA-4wwp-f6gw-6qm5
SiYuan: TLS Private Keys Readable via getFile (Incomplete Blocklist)
High Also affects github.com/siyuan-note/siyuan/kernel
GHSA-3cm4-ccvw-6xr6
SiYuan: /history/*path and /repo/diff/*path potentially exposing historical snapshots of data/.siyuan/publishAccess.json and data/templates/*
Medium Also affects github.com/siyuan-note/siyuan/kernel
GHSA-x8gv-g2g3-65fj
SiYuan Agent Tools SSRF via DNS-Rebinding TOCTOU (Bypass of CheckHostSSRF)
High Also affects github.com/siyuan-note/siyuan/kernel
GHSA-p23f-cm6q-2qp8
SiYuan MCP asset.upload Reads Arbitrary Absolute File Paths (Workspace Boundary Bypass)
Medium Also affects github.com/siyuan-note/siyuan/kernel
GHSA-rpx2-p6hp-x5gj
SiYuan: Missing consistency check between packageName and repoURL/repoHash in bazaar package install allows overwriting an existing, trusted plugin
Medium Also affects github.com/siyuan-note/siyuan/kernel
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor