Skip to content

Commit 979be19

Browse files
1 parent cb1f6e0 commit 979be19

6 files changed

Lines changed: 266 additions & 88 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-fxmw-rv85-5hwh",
4+
"modified": "2026-09-03T23:03:29Z",
5+
"published": "2026-08-12T21:31:41Z",
6+
"withdrawn": "2026-09-03T23:03:29Z",
7+
"aliases": [],
8+
"summary": "Duplicate Advisory: Missing publish-access filter on getAttributeViewKeysByID discloses database column schema, plus two unscoped block-ID enumeration oracles (publish mode)",
9+
"details": "## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-5fhr-f75j-8wr9. This link is maintained to preserve external references.\n\n## Original Description\nSiYuan versions before v3.7.4 fail to apply publish-access filtering to the getAttributeViewKeysByID endpoint, allowing authenticated readers to retrieve complete database column schemas including descriptions, select vocabularies, and template expressions. Additionally, getBlockDefIDsByRefText and getBlockRelevantIDs endpoints enumerate workspace-wide block IDs without publish scoping, enabling attackers to discover valid block identifiers across publish boundaries and access content from hidden or password-protected documents.",
10+
"severity": [
11+
{
12+
"type": "CVSS_V3",
13+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N"
14+
},
15+
{
16+
"type": "CVSS_V4",
17+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:L/SI:N/SA:N/E:X/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:X"
18+
}
19+
],
20+
"affected": [
21+
{
22+
"package": {
23+
"ecosystem": "Go",
24+
"name": "github.com/siyuan-note/siyuan/kernel"
25+
},
26+
"ranges": [
27+
{
28+
"type": "ECOSYSTEM",
29+
"events": [
30+
{
31+
"introduced": "0"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "< 3.7.4"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-5fhr-f75j-8wr9"
45+
},
46+
{
47+
"type": "ADVISORY",
48+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72800"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-unfiltered-api"
53+
}
54+
],
55+
"database_specific": {
56+
"cwe_ids": [
57+
"CWE-862"
58+
],
59+
"severity": "MODERATE",
60+
"github_reviewed": true,
61+
"github_reviewed_at": "2026-09-03T23:03:29Z",
62+
"nvd_published_at": "2026-08-12T20:17:51Z"
63+
}
64+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-hr3f-qfrh-h7w5",
4+
"modified": "2026-09-03T23:01:37Z",
5+
"published": "2026-08-12T21:31:41Z",
6+
"withdrawn": "2026-09-03T23:01:37Z",
7+
"aliases": [],
8+
"summary": "Duplicate Advisory: Encrypted-notebook key-derivation material and wrapped notebook keys disclosed to anonymous readers, enabling offline master-password cracking",
9+
"details": "## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-8x84-r2ff-h8pq. This link is maintained to preserve external references.\n\n## Original Description\nSiYuan versions before v3.7.4 disclose encrypted-notebook key-derivation material and wrapped data keys through unauthenticated endpoints in publish mode. Attackers can retrieve Argon2id salt, cost parameters, password verifiers, and wrapped notebook keys to perform unlimited offline master-password cracking without rate limiting.",
10+
"severity": [
11+
{
12+
"type": "CVSS_V3",
13+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"
14+
},
15+
{
16+
"type": "CVSS_V4",
17+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/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:X"
18+
}
19+
],
20+
"affected": [
21+
{
22+
"package": {
23+
"ecosystem": "Go",
24+
"name": "github.com/siyuan-note/siyuan/kernel"
25+
},
26+
"ranges": [
27+
{
28+
"type": "ECOSYSTEM",
29+
"events": [
30+
{
31+
"introduced": "0"
32+
},
33+
{
34+
"last_affected": "3.7.2"
35+
}
36+
]
37+
}
38+
]
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-8x84-r2ff-h8pq"
45+
},
46+
{
47+
"type": "ADVISORY",
48+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72801"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-encryption-key-material"
53+
}
54+
],
55+
"database_specific": {
56+
"cwe_ids": [
57+
"CWE-522"
58+
],
59+
"severity": "HIGH",
60+
"github_reviewed": true,
61+
"github_reviewed_at": "2026-09-03T23:01:37Z",
62+
"nvd_published_at": "2026-08-12T20:17:51Z"
63+
}
64+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-5fhr-f75j-8wr9",
4+
"modified": "2026-09-03T23:04:13Z",
5+
"published": "2026-09-03T23:04:13Z",
6+
"aliases": [
7+
"CVE-2026-72800"
8+
],
9+
"summary": "SiYuan: Missing publish-access filter on getAttributeViewKeysByID discloses database column schema, plus two unscoped block-ID enumeration oracles (publish mode)",
10+
"details": "**CVE:** This vulnerability corresponds to [CVE-2026-72800](https://nvd.nist.gov/vuln/detail/CVE-2026-72800).\n\n### Summary\n\n`POST /api/av/getAttributeViewKeysByID` returns a database's full column schema with no publish-access filtering, while its sibling `getAttributeViewKeys` applies the filter for reader sessions. Two further endpoints, `getBlockDefIDsByRefText` and `getBlockRelevantIDs` return workspace-wide block IDs with no publish scoping. All three are `CheckAuth`-only, so they are reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`.\n\n### Details\n\n**(a) `getAttributeViewKeysByID`: ungated column-schema disclosure**\n\nThe entire handler (`kernel/api/av.go`, router line 548):\n```go\nret.Data = model.GetAttributeViewKeysByID(avID, keyIDs...) // no publish gate\n```\n\nWith an empty `keyIDs`, `GetAttributeViewKeysByID` calls `av.ParseAttributeView(avID)` and returns every column's `*av.Key`:\n\n| Field | Discloses |\n|---|---|\n| `Name`, `Desc` | column title and user-authored description |\n| `Options` | the full single/multi-select vocabulary and colours (e.g. status labels such as \"Fired\", \"Confidential\") |\n| `Template` | the column's Sprig template expression — logic and field references |\n| `Relation` | the target `avID`, allowing pivot to another database |\n| `Rollup`, `NumberFormat`, date config | further schema |\n\n**Guarded-sibling asymmetry, same file:** `getAttributeViewKeys` (router line 526) runs `FilterBlockAttributeViewKeysByPublishAccess(...)` when `IsReadOnlyRoleContext`. `getAttributeViewKeysByID` applies nothing. A reader who knows an `avID` — trivially harvested from the `data-av-id` attribute of any published document embedding a database obtains the schema of any database in the workspace, including those whose host documents are hidden, password-protected, or publish-forbidden. `Relation` targets allow walking to sibling databases.\n\n**(b) Two unscoped block-ID enumeration oracles**\n\nBoth `CheckAuth`-only with no publish gate. Neither returns content of its own, but both yield valid block IDs that other endpoints turn into content:\n\n- `getBlockDefIDsByRefText` (router line 237) → `GetBlockDefIDsByRefText(anchor)` returns the block IDs, workspace-wide and including private documents, whose reference/anchor text equals a caller-supplied string: a ref-text → ID oracle.\n- `getBlockRelevantIDs` (router line 274) → `GetBlockRelevantIDsInBox(id, <notebook from request>)` returns parent/previous/next block IDs and traverses decrypted encrypted-notebook structure while the notebook is unlocked, a tree-walk oracle.\n\nVerified at `origin/master` (`eef105683`): all three handler bodies contain no publish-access, publish-ignore, or readonly-role check; all three routes are registered `CheckAuth` without `CheckAdminRole`.\n\n### Proof of Concept\n\nPrecondition: publish mode enabled (default port 6808); anonymous when `Publish.Auth.Enable` is `false`, otherwise any publish reader account. A database exists whose host document is publish-forbidden or password-protected.\n\n**(a) Column schema of any database:**\n```\nPOST http://127.0.0.1:6808/api/av/getAttributeViewKeysByID\n{\"avID\":\"<AV_ID>\"}\n```\nReturns every column's key object names, descriptions, select vocabularies, template expressions, and `Relation` target `avID`s for a database whose host document the reader may not access.\n\n**Control:** the sibling `getAttributeViewKeys` with the same `avID` returns filtered results for the same reader session, confirming the boundary is enforced there and omitted here.\n\n**(b) ID oracles:**\n```\nPOST http://127.0.0.1:6808/api/block/getBlockDefIDsByRefText\n{\"anchor\":\"<known ref text>\"}\n→ block IDs workspace-wide, including blocks in private documents\n\nPOST http://127.0.0.1:6808/api/block/getBlockRelevantIDs\n{\"id\":\"<BLOCK_ID>\",\"notebook\":\"<BOX_ID>\"}\n→ parent/previous/next block IDs; traverses encrypted-notebook structure when unlocked\n```\n\n### Impact\n\nAn anonymous reader (publish mode with auth disabled) or any publish `RoleReader` can read the complete column schema of any database in the workspace, including column descriptions, select-option vocabularies (which frequently encode sensitive category labels), template logic, and relation targets that permit pivoting to further databases regardless of whether the host document is hidden, password-protected, or excluded from publishing.\n\nThe two enumeration endpoints additionally supply valid block IDs across the publish boundary, including from encrypted notebooks while unlocked. This removes the \"attacker must already know a valid ID\" precondition from other block-read endpoints, converting ID knowledge into content disclosure. Confidentiality-only.\n\n### Note\n\ngetAttributeViewKeysByID is a distinct handler from getAttributeView; although column definitions also appear within the latter's response payload, a fix applied to one handler does not remediate the other, and getAttributeViewKeysByID has its own filtered sibling (getAttributeViewKeys) demonstrating the intended treatment.\n\n### Suggested fix\n\n- Gate `getAttributeViewKeysByID` with `FilterBlockAttributeViewKeysByPublishAccess`, mirroring `getAttributeViewKeys`.\n- Scope `getBlockDefIDsByRefText` and `getBlockRelevantIDs` to publish-accessible blocks for reader sessions, and ensure the `*InBox` traversal path applies the same check before walking encrypted-notebook structure.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/siyuan-note/siyuan/kernel"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.0.0-20260724103335-f36331956ae9"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-5fhr-f75j-8wr9"
42+
},
43+
{
44+
"type": "ADVISORY",
45+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72800"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/siyuan-note/siyuan/commit/931ba693375ea9877b2ef74f9bfb632fad5bab3f"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://github.com/siyuan-note/siyuan/commit/f36331956ae98fc5358f8f93bf1da3427221edf3"
54+
},
55+
{
56+
"type": "PACKAGE",
57+
"url": "https://github.com/siyuan-note/siyuan"
58+
},
59+
{
60+
"type": "WEB",
61+
"url": "https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-unfiltered-api"
62+
}
63+
],
64+
"database_specific": {
65+
"cwe_ids": [
66+
"CWE-862"
67+
],
68+
"severity": "MODERATE",
69+
"github_reviewed": true,
70+
"github_reviewed_at": "2026-09-03T23:04:13Z",
71+
"nvd_published_at": null
72+
}
73+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-8x84-r2ff-h8pq",
4+
"modified": "2026-09-03T23:02:12Z",
5+
"published": "2026-09-03T23:02:12Z",
6+
"aliases": [
7+
"CVE-2026-72801"
8+
],
9+
"summary": "SiYuan: Encrypted-notebook key-derivation material and wrapped notebook keys disclosed to anonymous readers, enabling offline master-password cracking",
10+
"details": "**CVE:** This vulnerability corresponds to [CVE-2026-72801](https://nvd.nist.gov/vuln/detail/CVE-2026-72801).\n\n### Summary\n\nTwo `CheckAuth`-only endpoints disclose the complete offline attack material for the encrypted-notebook master password, plus the wrapped per-notebook key needed to use it. Both are reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`. An unauthenticated remote client can retrieve the Argon2id salt and cost parameters, a verifier that confirms a correct password offline, and the encrypted per-notebook data key reducing the security of every encrypted notebook to the master password's resistance to offline GPU cracking.\n\n### Details\n\n**(1) `POST /api/system/getConf` leaks `NotebookCrypto`.**\n\n`getConf` → `GetMaskedConf()` marshals the full configuration including `NotebookCrypto *conf.NotebookCrypto` (JSON tag `notebookCrypto`, not `-`, so it survives the deep copy). For non-administrators `HideConfSecret()` is applied, which nulls a dozen secret-bearing fields like AI, MCPOAuth, Api, Flashcard, Publish, Repo, Sync, Secrets, Variables, System paths but contains **no reference to `NotebookCrypto`**. `FilterConfByPublishIgnore()` for readers only touches `UILayout`.\n\nThe reader therefore receives:\n\n| Field | What it is |\n|---|---|\n| `MasterSalt` | global Argon2id salt |\n| `KDFParams` | Argon2id memory/time/parallelism cost |\n| `KEKVerifier` + `VerifierNonce` | AES-GCM-encrypted fixed magic, the in-code comment states it exists for offline master-password verification |\n| `KEKMAC` | HMAC-SHA256 of the KEK |\n\nEither `KEKVerifier` or `KEKMAC` is a self-contained offline oracle:\n\n```\nKEK = Argon2id(guess, MasterSalt, KDFParams)\ncorrect if AES-GCM-decrypt(KEKVerifier, VerifierNonce) == magic\n or HMAC(KEK) == KEKMAC\n```\n\nNo server round-trips are required, so there is no rate limiting, lockout, or logging on guesses, and the work is fully GPU-parallelisable.\n\n**(2) `POST /api/notebook/getNotebookConf` leaks the wrapped data key.**\n\n`box.GetConf()` returns the full `BoxConf` including `BoxCrypt.WrappedDEK`, the per-notebook data-encryption key wrapped under the KEK via AES-GCM together with `WrapNonce`. `getNotebookInfo` is the same class. Once (1) yields the master password, the attacker derives the KEK, decrypts `WrappedDEK` to recover the real data-encryption key, and decrypts every `.sy` file in that notebook.\n\n**Why this matters beyond the at-rest threat model.** Storing verifier and KDF material alongside the ciphertext is reasonable against a *local* attacker who already has filesystem access. Serving `MasterSalt` + `KDFParams` + `KEKVerifier` + `WrappedDEK` to an *anonymous remote reader* converts that at-rest assumption into a remote pre-authentication cracking opportunity.\n\n**Guarded-sibling asymmetry.** `HideConfSecret` nulls a dozen secret fields but omits `NotebookCrypto`. `lsNotebooks` filters notebook visibility for readers, while `getNotebookConf` and `getNotebookInfo` apply no reader filter at all.\n\nVerified at `origin/master` (`eef105683`): handler bodies as described; `HideConfSecret` contains zero `NotebookCrypto` matches; `FilterConfByPublishIgnore` touches only `UILayout`; all relevant struct JSON tags are non-`-`; all three routes are registered `CheckAuth` without `CheckAdminRole`.\n\n### Proof of Concept\n\nPrecondition: publish mode enabled (default port 6808) with at least one encrypted notebook configured; anonymous when `Publish.Auth.Enable` is `false`, otherwise any publish reader account.\n\n**1. Retrieve the key-derivation material as an anonymous reader:**\n```\nPOST http://127.0.0.1:6808/api/system/getConf\n{}\n```\nThe response's `notebookCrypto` object contains `MasterSalt`, `KDFParams`, `KEKVerifier`, `VerifierNonce`, and `KEKMAC` while the same response has the other secret fields (Api, Repo, Sync, Publish, System paths) correctly blanked, demonstrating the omission.\n\n**2. Retrieve the wrapped notebook key:**\n```\nPOST http://127.0.0.1:6808/api/notebook/getNotebookConf\n{\"notebook\":\"<NOTEBOOK_ID>\"}\n```\nThe response contains `BoxCrypt.WrappedDEK` and `WrapNonce`.\n\n**3. Offline:** candidate passwords are verified locally against `KEKVerifier`/`KEKMAC` using `MasterSalt` and `KDFParams`, with no further server interaction. A recovered password yields the KEK, which unwraps `WrappedDEK` to the notebook's data-encryption key.\n\n*Verification status:* the leak paths are confirmed by code inspection at `origin/master`. A live end-to-end demonstration requires a build from HEAD with an encrypted notebook enabled; the test instance available predates the encrypted-notebook feature, so no runtime reproduction is claimed here.\n\n### Impact\n\nAn unauthenticated remote client (publish mode with auth disabled) or any publish `RoleReader` obtains everything needed to mount an unlimited, unthrottled, GPU-parallel offline attack on the encrypted-notebook master password, plus the wrapped data key to decrypt notebook contents once the password is recovered. The confidentiality of every encrypted notebook then rests solely on master-password entropy against an offline attacker, rather than on the password remaining unknown to remote parties. No rate limiting or detection applies, because guessing occurs entirely off-server.\n\n### Suggested fix\n\n- In `HideConfSecret`, replace `NotebookCrypto` with a minimal `{enabled: bool}` for non-administrators the frontend only needs the enabled flag for the lock UI stripping `MasterSalt`, `KDFParams`, `KEKVerifier`, `VerifierNonce`, and `KEKMAC`.\n- Apply reader filtering to `getNotebookConf` and `getNotebookInfo` so `BoxCrypt` (including `WrappedDEK` and `WrapNonce`) is omitted for non-administrator roles.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/siyuan-note/siyuan/kernel"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.0.0-20260724102025-3bc014c7dc32"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-8x84-r2ff-h8pq"
42+
},
43+
{
44+
"type": "ADVISORY",
45+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72801"
46+
},
47+
{
48+
"type": "PACKAGE",
49+
"url": "https://github.com/siyuan-note/siyuan"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-encryption-key-material"
54+
}
55+
],
56+
"database_specific": {
57+
"cwe_ids": [
58+
"CWE-522"
59+
],
60+
"severity": "HIGH",
61+
"github_reviewed": true,
62+
"github_reviewed_at": "2026-09-03T23:02:12Z",
63+
"nvd_published_at": null
64+
}
65+
}

0 commit comments

Comments
 (0)