GHSA-gw25-m53r-qh88: Path Traversal

Published Sep 3, 2026
·
Updated

Summary SiYuan's /export/ file handler was hardened against export disclosure (issue #12213) by adding an IsSubPath(exportBaseDir, fullPath) check and an IsSensitivePath() check in commit bb481e1. These guards were added only to the main branch of the handler. The handler begins with a short-circuit branch: go if strings.HasPrefix(c.Request.URL.Path, "/export/temp/") { c.File(filepath.Join(util.TempDir, c.Request.URL.Path)) return } This branch joins the broader util.TempDir with the raw, percent-decoded request path and serves it with neither IsSubPath nor IsSensitivePath. An authenticated request to /export/temp/%2e%2e/.../etc/passwd traverses out of TempDir and reads arbitrary files - exactly the sensitive-file disclosure the patch intended to prevent. Present in the latest master.

Affected - From commit bb481e1 (the hardening) through the latest master. - Requires SiYuan access authorization (model.CheckAuth) - but the patch's stated goal is to deny sensitive-file export even to authorized callers.

Root cause kernel/server/serve.go serveExport(): the main branch has IsSubPath + IsSensitivePath; the /export/temp/ short-circuit branch (above it) has neither and uses util.TempDir as its root. c.Request.URL.Path is percent-decoded by net/http, so %2e%2e becomes .. and filepath.Join collapses it.

Incomplete-fix lineage - Export disclosure (issue #12213; CVE-2026-30869) -> fix bb481e1 / d68bd5a (GHSA-6865-qjcf-286f): guards on the main branch + IsSensitivePath extended to .db/.log. - Follow-up CVE-2026-41894 (GHSA-hjh7-r5w8-5872) in the same /export path family. - The /export/temp/ short-circuit branch was never covered by the guards (this report).

Proof of concept (benign) 1. Authenticate (access auth code). 2. GET /export/<sensitive> (main branch) -> 401/403 (guards work). 3. GET /export/temp/%2e%2e/%2e%2e/.../tmp/<planted-marker> (or /etc/hostname) -> 200 + file content, demonstrating the unguarded traversal. The PoC reads only a planted marker / /etc/hostname; no credentials.

Impact Authenticated arbitrary file read bypassing the sensitive-file protection: /etc/passwd, ~/.ssh/, SiYuan .db workspace data, .log.

Remediation - Apply IsSubPath + IsSensitivePath to the /export/temp/ branch (or restrict its root to TempDir/temp with an IsSubPath check). - filepath.Clean the request path and reject ... - Merge both branches into one guarded file-serving function.

References - Hardening advisory: https://github.com/siyuan-note/siyuan/security/advisories/GHSA-6865-qjcf-286f (commit d68bd5a); issue #12213. - CVE chain: CVE-2026-30869 -> CVE-2026-41894 (GHSA-hjh7-r5w8-5872). - serve.go guards commit: https://github.com/siyuan-note/siyuan/commit/bb481e1290c4a34255652ede85a546504505d2a7 - Residual source (master): kernel/server/serve.go serveExport() lines 308-312.

Affected Software

1 affected componentFixes available
go/github.com/siyuan-note/siyuan/kernel<0.0.0-20260510110132-b763d787d1f2
0.0.0-20260510110132-b763d787d1f2

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-20260510110132-b763d787d1f2
  2. Upgrade

    Upgrade siyuan to a version that resolves this vulnerability.

    Fixed in d68bd5aPatch GHSA-6865-qjcf-286f
  3. Configuration

    In serveExport(), remove the short-circuit that serves files from the raw percent-decoded c.Request.URL.Path under /export/temp/. Instead, ensure the /export/temp/ branch is guarded equivalently to the main /export/ handler: join to a safe root (TempDir/temp or export base dir) using a cleaned path (filepath.Clean) and explicitly reject '..' traversal, then enforce IsSubPath(exportBaseDir, fullPath) and IsSensitivePath checks (including the extended patterns for sensitive files such as *.db/*.log as described in the hardening).

    siyuan kernel/server/serve.go (serveExport) Export temp path handling guards = Apply IsSubPath + IsSensitivePath to the /export/temp/ branch (or restrict its root to TempDir/temp) and reject path traversal via filepath.Clean and rejecting '..'

Event History

Sep 3, 2026
Advisory Published
via GitHub·02:56 PM
Data Sourced
via GitHub·02:56 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Who can exploit this issue?

An attacker needs SiYuan access authorization because the export handler requires authentication. Any authenticated caller able to send requests to the affected endpoint may attempt exploitation over the network.

2

What does an attacker need to send?

The attacker needs a crafted request under /export/temp/ containing percent-decoded traversal sequences, such as %2e%2e, to escape the temporary directory. No user interaction is required.

3

Which code revisions are affected?

The issue is present from commit bb481e1, which added hardening to the main export-handler path, through the latest master identified by the advisory. The provided data does not identify affected release version numbers.

4

How can I determine whether my code is vulnerable?

Inspect kernel/server/serve.go in serveExport(). The vulnerable implementation has a /export/temp/ short-circuit that serves filepath.Join(util.TempDir, c.Request.URL.Path) without IsSubPath or IsSensitivePath validation.

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