GHSA-vg99-7gj7-2fr5: Medium severity go/github.com/siyuan-note/siyuan/kernel vulnerability

Published Oct 1, 2026
·
Updated

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 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:

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

FilterRefDefsByPublishIgnore (kernel/model/publishaccess.go:1324) collects the reference and definition identifiers, resolves their block trees, and delegates the decision to FilterBlockTreesByPublishIgnore (:1314), whose entire body is:

go 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/publishaccess.go:431:

go 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 document | Anonymous result | |---|---| | Public | reference returned (baseline) | | Password-protected | reference 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 Software

1 affected componentFixes available
go/github.com/siyuan-note/siyuan/kernel<0.0.0-20260812083335-251596fc0de2
0.0.0-20260812083335-251596fc0de2

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade go/github.com/siyuan-note/siyuan/kernel to a version that resolves this vulnerability.

    Fixed in 0.0.0-20260812083335-251596fc0de2
  2. Compensating control

    Fix /api/block/getRefIDs by threading *gin.Context through FilterRefDefsByPublishIgnore and FilterBlockTreesByPublishIgnore, and replacing the bare CheckPathAccessableByPublishIgnore call with checkBlockTreeAccessableByPublishAccess so the publish-password tier and encrypted-box check are applied.

Event History

Oct 1, 2026
Advisory Published
via GitHub·04:29 PM
Data Sourced
via GitHub·04:29 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

What access does an attacker need?

The issue affects reader-role users who have not entered a document's publish password. The affected handler is protected by model.CheckAuth, but it does not apply a read-only or admin-role check.

2

What information can be disclosed?

A reader who lacks the publish password can learn that a password-protected document references a particular block. The disclosure is limited to reference relationship information; no integrity or availability impact is described.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203