GHSA-h4v5-crx2-3cv4: High severity go/github.com/siyuan-note/siyuan/kernel vulnerability

Published Sep 4, 2026
·
Updated

CVE: This vulnerability corresponds to 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 returning it CookieKey, NotebookCrypto, Export.PandocBin, Account, Stat, System.ID, the AI keys. That cloner is the project's own working inventory of what must not leave the server. getConf's non-administrator path maintains a separate, shorter list that has now diverged from it in three places. Any future secret added to the config will default to exposed on the reader path unless someone remembers to extend the blocklist.

Proof of Concept

Precondition: publish mode enabled (default port 6808); anonymous when Publish.Auth.Enable is false, otherwise any publish reader account.

POST http://127.0.0.1:6808/api/system/getConf {}

→ 200. The conf object contains: cookieKey — the session-signing key, cleartext export.pandocBin — absolute path containing the OS username notebookCrypto — encrypted-notebook key material

Differential check against the endpoint that strips them, same instance:

POST http://127.0.0.1:6808/api/system/exportConf

→ cookieKey is empty, export.pandocBin is empty, notebookCrypto is null

The same three values are withheld by one endpoint and returned by the other.

Impact

An anonymous reader in publish mode or any publish RoleReader obtains the server's session-cookie signing key, permitting forgery and tampering of session cookies the server validates as authentic, with administrator authentication reachable on instances that have no access-auth code configured. The same response discloses the operating-system username and workspace layout, defeating a control added specifically to prevent that disclosure, and encrypted-notebook key material.

Suggested fix

Route non-administrator getConf responses through the exportConf cloner rather than extending HideConfSecret field by field. The cloner already handles every field named here and is the list the project actually maintains; keeping two divergent inventories of the same secrets is what produced all three gaps. If a targeted patch is preferred in the interim, clear CookieKey and NotebookCrypto in HideConfSecret and add Export.PandocBin to the IsBrowserRequest block, then audit the config struct for any remaining absolute-path or secret-bearing field.

Affected Software

1 affected componentFixes available
go/github.com/siyuan-note/siyuan/kernel<0.0.0-20260725132049-2d8b98395a91
0.0.0-20260725132049-2d8b98395a91

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade go/github.com/siyuan-note/siyuan/kernel to a version that resolves this vulnerability.

    Fixed in 0.0.0-20260725132049-2d8b98395a91
  2. Configuration

    In HideConfSecret (used by the non-administrator masking chain), clear Conf.CookieKey so the live session-cookie signing key is not returned via /api/system/getConf.

    SiYuan kernel/api/system.go (HideConfSecret / getConf masking chain) Conf.CookieKey = cleared/empty (set to empty) for non-admin readers
  3. Configuration

    In HideConfSecret (used by the non-administrator masking chain), clear Conf.NotebookCrypto so encrypted-notebook key material is not returned via /api/system/getConf.

    SiYuan kernel/api/system.go (HideConfSecret / getConf masking chain) Conf.NotebookCrypto = null
  4. Configuration

    Add Conf.Export.PandocBin to the IsBrowserRequest (browser-request path strip) block so absolute pandoc paths (export.pandocBin) are not returned to readers via /api/system/getConf.

    SiYuan kernel/api/system.go (HideConfSecret / browser-request stripping) Conf.Export.PandocBin = block/omit for browser-request path (add to IsBrowserRequest block)
  5. Compensating control

    Mitigate by ensuring Publish.Auth.Enable is true and that anonymous access is not permitted for publish mode; /api/system/getConf is reachable anonymously when Publish.Auth.Enable is false.

  6. Operational

    Because the session cookie is signed with Conf.CookieKey (the value handed out by the endpoint), rotate/renew session state after applying the fix to invalidate active sessions (the material notes rotating invalidates every active session).

Event History

Sep 4, 2026
Advisory Published
via GitHub·09:16 PM
Data Sourced
via GitHub·09:16 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Who can retrieve the exposed configuration values?

A user with the publish RoleReader token can reach the endpoint. It is also reachable anonymously when Publish.Auth.Enable is false.

2

What does an attacker need to exploit this issue?

The endpoint is network-accessible and requires no privileges beyond a publish RoleReader token; when publish authentication is disabled, no authentication is needed. The affected route is POST /api/system/getConf.

3

Which sensitive values may be disclosed?

The response may include the session-cookie signing key (cookieKey), encrypted-notebook key material (notebookCrypto), and the absolute Pandoc binary path (export.pandocBin), which can embed the operating-system username.

4

How can I determine whether anonymous access is possible in my deployment?

Check whether Publish.Auth.Enable is false. If it is false, the getConf endpoint is reachable anonymously; otherwise, a publish RoleReader token can access it.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203