SiYuan: Authorization Bypass Allows Low-Privilege Publish User to Modify Notebook Content via /api/block/appendHeadingChildren
Date: 2026-03
Affected: go/github.com/siyuan-note/siyuan/kernel
Attack vector: auth-bypass
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-30926
CWE: CWE-284
CWE-862
CVSS: 7.1 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:N)

### Summary A privilege escalation vulnerability exists in the publish service of SiYuan Note that allows a low-privilege publish account (RoleReader) to modify notebook content via the `/api/block/appendHeadingChildren` API endpoint. The endpoint only requires `model.CheckAuth`, which accepts `RoleReader` sessions. Because the endpoint performs a persistent document mutation and does not enforce `CheckAdminRole` or `CheckReadonly`, a publish user with read-only privileges can append new blocks to existing documents. This allows remote authenticated publish users to modify notebook content and compromise the integrity of stored notes. ### Details File: router.go, block.go, block.go, session.go Lines: router.go:245, api/block.go:193-205, model/block.go:688-714, model/session.go:201-209 Vulnerable Code: ``` - router.go: ginServer.Handle("POST", "/api/block/appendHeadingChildren", model.CheckAuth, appendHeadingChildren) - api/block.go: model.AppendHeadingChildren(id, childrenDOM) - model/block.go: indexWriteTreeUpsertQueue(tree) (persists document mutation) - session.go: CheckAuth accepts RoleReader as authenticated ``` Why Vulnerable: A low-privilege publish account (RoleReader, read-only) passes CheckAuth, but this write endpoint lacks CheckAdminRole and CheckReadonly. The handler performs persistent document writes. ### PoC 1. Enable publish service and create low-privilege account ``` curl -u workspace:<ACCESS_AUTH_CODE> \ -H "Content-Type: application/json" \ -d '{


Mitigations:

Architectural layers (MAESTRO):