GITHUB.COM/SIYUAN-NOTE/SIYUAN/KERNEL · CVE-2026-41894 · Package
FIX → 3.6.5
SiYuan's `/export/` handler decodes file paths twice, so a request with `%252e%252e` escapes the export folder. An attacker with an account can then download the document database, the block tree database and the kernel log.
first public Apr 19, 2026 · 2 sources
Could this affect your app?
Free first check from your website. Connect your repo for the full answer.
Teams that run a self-hosted SiYuan server, or expose its Publish service, where users have accounts. The flaw is in the /export/ path handling of the kernel, so a standalone desktop install with no network access is not exposed to remote attackers.
Not affected if auth-required, managed-hosting, no-publish-service
Who cares go, self-hosted, siyuan
go:github.com/siyuan-note/siyuan/kernel is affected below 3.6.5./export/%25 requests in web server or reverse proxy access logs.Upgrade to 3.6.5
3.6.5 or later.The fix for CVE-2026-30869 in SiYuan v3.5.10 only added a denylist check (IsSensitivePath) but did not address the root cause — a redundant url.PathUnescape() call in serveExport(). An authenticated attacker can use double URL encoding (%252e%252e) to traverse directories and read arbitrary workspace files including the full SQLite database (siyuan.db), kernel log, and all user documents.
In kernel/server/serve.go, the serveExport() function (line 314-320) processes file paths as follows:
filePath := strings.TrimPrefix(c.Request.URL.Path, "/export/")
decodedPath, err := url.PathUnescape(filePath) // second decode
fullPath := filepath.Join(exportBaseDir, decodedPath)
Go's HTTP server already decodes percent-encoded characters once during request parsing. The additional url.PathUnescape() call creates a double-decode vulnerability:
Are you affected?
Tell InfraStack what you run. It checks this one, and every next one, against your stack.
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
GET /export/%252e%252e/siyuan.db%25 → %, result: URL.Path = /export/%2e%2e/siyuan.db%2e%2e as literal characters (not ..), no redirect occursurl.PathUnescape("%2e%2e") decodes to ..filepath.Join(exportBaseDir, "../siyuan.db") resolves to <workspace>/temp/siyuan.dbThe CVE-2026-30869 fix added IsSensitivePath() which blocks <workspace>/conf/ and OS-level paths (/etc, /root, etc.). However, it does NOT block:
<workspace>/temp/siyuan.db — full document database<workspace>/temp/blocktree.db — block tree database<workspace>/temp/siyuan.log — kernel log<workspace>/temp/asset_content.db — asset content databaseNote: the /appearance/ handler in the same file correctly uses gulu.File.IsSubPath() to validate paths (line 447), but this check is missing from the /export/ handler.
poc.zip Please extract the uploaded compressed file before proceeding
siyuan.log) leaks internal server paths, versions, configuration details, and error messages.This page as .md · .json · CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/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
GitHub Advisory Database, CC-BY 4.0 · NVD data is provided by NIST and is public domain. Posts quoted belong to their authors.