CVE-2026-72793: siyuan · Insufficiently Protected Credentials
Affects siyuanSource CVE Database V5
Not known to be exploited · CVSS 9.2 Critical : upgrade to 3.7.4 as a priority.
Data as of 9 Nov 2026, 23:24 UTC
- EPSS
- 0.3% chance of exploitation in 30 days – higher than 23% of CVEsExploit Prediction Scoring System: the likelihood attackers will use this flaw soon.
- Patch
- Available – fixed in 3.7.4
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:NExploitation evidence
Disclosed: evidence found.
CVE published 12 Aug 2026
Detectable: no evidence on record.
No public nuclei template indexed
Weaponized: no evidence on record.
No public exploit code indexed in Metasploit or Exploit-DB
Exploited in the wildExploited: no evidence on record.
Not in CISA KEV and no source reports exploitation
Observed by OffSeq MirageSeen by Mirage: no evidence on record.
No attack traffic recorded by OffSeq Mirage sensors
A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 10 Nov 2026.
What to do
Upgrade siyuan and siyuan-note/siyuan to 3.7.4.
Affected software
| Product | Affected | Fixed in |
|---|---|---|
| siyuan-notesiyuan | Affected
| Fixed in
|
GitHubsiyuan-note/siyuanpkg:github/siyuan-note/siyuanOther threats | Affected
| Fixed in
|
Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.
AI-suggested
If you cannot patch yet, restrict access to the /api/system/getConf endpoint and configure access-auth codes to prevent unauthorized privilege escalation.
Description
**CVE:** This vulnerability corresponds to [CVE-2026-72793](https://nvd.nist.gov/vuln/detail/CVE-2026-72793). ### Summary `/api/system/getConf` is registered with `CheckAuth` only and is reachable by the publish `RoleReader` token, and anonymously when `Publish.Auth.Enable` is `false`. Its non-administrator masking chain is a blocklist that enumerates fields individually. Three fields that the configuration-export endpoint in the same file deliberately clears are absent from that blocklist and are returned to readers: | Field | JSON | What it is | Cleared by `exportConf` at | |---|---|---|---| | `Conf.CookieKey` | `cookieKey` | The session-cookie signing key | `kernel/api/system.go:360` | | `Conf.Export.PandocBin` | `export.pandocBin` | Absolute path embedding the OS username | `kernel/api/system.go:338` | | `Conf.NotebookCrypto` | `notebookCrypto` | Encrypted-notebook key material | `kernel/api/system.go:360` | The project has already classified all three as values that must not leave the server. The reader-facing path returns them. ### Details **Route.** `kernel/api/router.go:70` : `POST /api/system/getConf` → `model.CheckAuth` → `getConf`. No `CheckReadonly`, no `CheckAdminRole`. **The masking chain, and what each stage covers.** `getConf` masks through `GetMaskedConf()` → `HideConfSecret()` (non-administrators) → `FilterConfByPublishIgnore()` (readers) → a browser-request path strip. - `GetMaskedConf`: `UserData`, `MCPOAuth`, `AccessAuthCode`. - `HideConfSecret`: `AI`, `Api`, `Flashcard`, `ServerAddrs`, `Publish`, `Repo`, `Sync`, `Secrets`, `Variables`, and the System paths. No reference to `CookieKey` or `Export.PandocBin`. - `FilterConfByPublishIgnore`: `UILayout` only. - Browser strip (`kernel/api/system.go:630-631`): System paths only. Each stage names fields explicitly, so any field nobody thought to add is returned by default. --- **1. `CookieKey`: the live session-signing key.** The value is passed straight into the session store at startup: ``` cli/cmd/serve.go:67 go server.Serve(false, model.Conf.CookieKey) kernel/server/serve.go:152 sessionStore = cookie.NewStore([]byte(cookieKey)) kernel/server/serve.go:159 ginServer.Use(sessions.Sessions("siyuan", sessionStore)) ``` `gin-contrib/sessions/cookie.NewStore` constructed with a single key uses that key as the `gorilla/securecookie` HMAC key. The `siyuan` session cookie is signed with the value this endpoint hands out, so an attacker holding it can mint and modify session cookies the server accepts as authentic. Escalating a forged session to administrator additionally requires the forged `SessionData` to carry the matching `AccessAuthCode` which *is* masked or the instance to have no access-auth code configured, which is a common deployment. The unconditional impact, present on every instance, is disclosure of a persistent cryptographic secret to an unauthenticated party. Rotating it invalidates every active session, so it cannot be quietly refreshed. --- **2. `Export.PandocBin`: bypasses a shipped privacy control.** The field is an absolute path that embeds the OS username by construction: ``` conf/export.go:35 PandocBin string `json:"pandocBin"` model/conf.go:430-431 if "" == Conf.Export.PandocBin { Conf.Export.PandocBin = util.PandocBinPath } util/pandoc.go:154 PandocBinPath = filepath.Join(tempPandocDir, "bin", "pandoc.exe") util/pandoc.go:134 tempPandocDir = filepath.Join(TempDir, "pandoc") util/working.go:359 TempDir = filepath.Join(WorkspaceDir, "temp") util/working.go:312 defaultWorkspaceDir = filepath.Join(userProfile, "SiYuan") ``` → `C:\Users\<username>\SiYuan\temp\pandoc\bin\pandoc.exe` This one is notable beyond the disclosure itself, because a control was shipped specifically to prevent it. `kernel/api/system.go:630` adds, for browser requests: ```go if util.IsBrowserRequest(c) { maskedConf.System.WorkspaceDir = "" maskedConf.System.AppDir = "" maskedConf.System.ConfDir = "" maskedConf.System.DataDir = "" maskedConf.System.HomeDir = "" } // 避免泄露用户名等敏感信息 ``` The comment states the goal plainly: avoid leaking the username and other sensitive information. The block enumerates only `System.*` and misses `Export.PandocBin`, which carries the same username through the same response. A publish reader is a browser request, so the System paths are blanked while `export.pandocBin` passes through intact. Where an administrator has configured a custom pandoc location, that path is disclosed instead still a filesystem-layout disclosure. --- **3. `NotebookCrypto`.** Encrypted-notebook key material is likewise absent from `HideConfSecret` while `exportConf` sets it to `nil`. Reported previously and included here only because it is the third instance of the same root cause; the fix below closes all three together. --- **The root cause is the blocklist itself.** `exportConf` (`kernel/api/system.go:299`) clones the configuration and clears each secret before