CVE-2026-59834: SiYuan SQL Injection via Block Search paths Parameter
SiYuan's block search API lets an unauthenticated publish visitor smuggle a UNION SELECT through the paths[] parameter to read private note content that the publish visibility system is supposed to…

The problem
The POST /api/search/fullTextSearchBlock endpoint parses each entry in paths[] into a notebook ID and a path prefix, then concatenates both values directly into a SQLite WHERE clause using fmt.Sprintf. No escaping or validation is applied.
The publish service forwards requests from unauthenticated visitors with a reader-role token. Because the API only blocks method=2 (explicit SQL mode) for non-admins, every other search mode, such as regexp (method=3), still reaches the vulnerable string-building code.
The post-query publish filter trusts the box and path columns in the returned rows, so an injected row that projects a visible document's coordinates passes the filter even when its content came from a hidden document.
Proof of concept
A working proof-of-concept for CVE-2026-59834 in github.com/siyuan-note/siyuan/kernel, with the exact payload below.
POST /api/search/fullTextSearchBlock HTTP/1.1
Host: <publish-service-host>
Content-Type: application/json
{
"query": "SECRET-LIVE-SQLI-20260609",
"method": 3,
"page": 1,
"pageSize": 10,
"paths": [
"VISIBLE_NOTEBOOK_ID/x%') UNION SELECT id,parent_id,root_id,hash,'VISIBLE_NOTEBOOK_ID','/VISIBLE_DOC.sy',hpath,name,alias,memo,tag,content,fcontent,markdown,length,type,subtype,ial,sort,created,updated FROM blocks WHERE path='/HIDDEN_DOC.sy' -- "
]
}The path string is split on the first / to extract box and path, then each is written into SQL with fmt.Sprintf("box = '%s'", box) and fmt.Sprintf("path LIKE '%s%%'", path). The injected value closes the LIKE string literal with %'), appends a UNION SELECT that reads from the hidden document, and projects VISIBLE_NOTEBOOK_ID and /VISIBLE_DOC.sy as the returned box and path columns.
The regexp search engine executes the fully assembled statement before any access check runs. FilterBlocksByPublishAccess then inspects only the projected box and path from each returned row, sees the visible document's coordinates, and passes the injected hidden row through to the caller.
The fix replaces string concatenation with bound SQL parameters (box = ?, path LIKE ?) and adds input validation on notebook IDs and path format before query construction.
The fix
Upgrade to SiYuan v3.7.1 (commit d0f0fe146fb07d594fcadc4f48d4f7c30ac01d1e). The patch rewrites the box and path predicates in kernel/model/search.go to use parameterized queries instead of fmt.Sprintf string concatenation, and adds notebook ID and .sy path format validation in kernel/api/search.go before values reach the query builder.
As an interim measure if upgrading is not possible, block unauthenticated access to POST /api/search/fullTextSearchBlock at the network or reverse-proxy level.
Related research
- high · 7.7CVE-2026-59832CVE-2026-59832: SiYuan Authenticated Path Traversal in /snippets/ Handler
- critical · 9.9CVE-2026-50551CVE-2026-50551: SiYuan Stored XSS to RCE via Attribute View Asset Cell
- high · 7.5CVE-2026-54066CVE-2026-54066: SiYuan Unauthenticated Path Traversal via Double URL Encoding in /assets/ (Publish Mode)
- critical · 9.9CVE-2026-54067CVE-2026-54067: SiYuan Stored XSS to RCE via CSS Snippet Style Tag Breakout