{"id":"GO-2026-6373","revision":null,"records":[{"revision":"80b2a1f8e31d4f7daee77436666dabff","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-69086","aliases":[],"title":"SiYuan before v3.7.3 Path Traversal via unvalidated avID","description":"SiYuan versions before v3.7.3 fail to validate the avID parameter on all code branches in attribute-view read endpoints, allowing attackers to construct traversal paths that escape the storage directory. Authenticated users with RoleReader permissions or anonymous clients when publish authentication is disabled can read JSON files outside the attribute-view directory to disclose cross-scope database content.","state":0,"publishedAt":"2026-08-03T13:20:41.535+00:00","modifiedAt":"2026-08-14T16:51:13.344+00:00","affected":[{"ecosystem":"Vendor product","name":"siyuan","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"siyuan-note\",\n                    \"product\": \"siyuan\",\n                    \"defaultStatus\": \"unaffected\",\n                    \"packageURL\": \"pkg:golang/github.com/siyuan-note/siyuan/kernel\",\n                    \"versions\": [\n                        {\n                            \"version\": \"0\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"semver\",\n                            \"lessThan\": \"3.7.3\"\n                        },\n                        {\n                            \"version\": \"3.7.3\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"semver\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N","score":8.3,"severity":"HIGH"},{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N","score":7.7,"severity":"HIGH"}],"references":["https://github.com/siyuan-note/siyuan/security/advisories/GHSA-7hm9-v7vf-7g4w","https://www.vulncheck.com/advisories/siyuan-before-path-traversal-via-unvalidated-avid"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-69086","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-69086","identifiers":["CVE-2026-69086"]},"retained":false,"historicalAffected":[]},{"revision":"dc30a2ffdfc2443db0f7d13712ffb5cf","observedAt":"2026-10-25T15:18:51.467+00:00","statement":{"source":"nvd","id":"CVE-2026-69086","aliases":[],"title":"SiYuan versions before v3.7.3 fail to validate the avID parameter on all code branches in attribute-view read endpoints, allowing attackers to construct traversal paths that escape the storage directory. Authenticated users with RoleReader …","description":"SiYuan versions before v3.7.3 fail to validate the avID parameter on all code branches in attribute-view read endpoints, allowing attackers to construct traversal paths that escape the storage directory. Authenticated users with RoleReader permissions or anonymous clients when publish authentication is disabled can read JSON files outside the attribute-view directory to disclose cross-scope database content.","state":0,"publishedAt":"2026-08-03T14:16:28.96+00:00","modifiedAt":"2026-10-23T21:10:00.157+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · disclosure@vulncheck.com · Secondary","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:H/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","score":8.3,"severity":"HIGH"},{"system":"CVSS 3.1 · disclosure@vulncheck.com · Secondary","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N","score":7.7,"severity":"HIGH"}],"references":["https://github.com/siyuan-note/siyuan/security/advisories/GHSA-7hm9-v7vf-7g4w","https://www.vulncheck.com/advisories/siyuan-before-path-traversal-via-unvalidated-avid"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-69086","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-22"],"productCriteria":[],"sourceDates":{"published":"2026-08-03T14:16:28.960","lastModified":"2026-10-23T21:10:00.157"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-69086","identifiers":["CVE-2026-69086"]},"retained":false,"historicalAffected":[]},{"revision":"833984e37acd4466a68b29e7f48f1bad","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GHSA-7hm9-v7vf-7g4w","aliases":["CVE-2026-69086","GO-2026-6373"],"title":"SiYuan: Path Traversal via unvalidated avID in RenderAttributeView/AV read endpoints : reader-reachable cross-scope attribute-view disclosure","description":"**CVE:** This vulnerability corresponds to [CVE-2026-69086](https://nvd.nist.gov/vuln/detail/CVE-2026-69086).\n\n### Summary\n\nFour attribute-view read endpoints build a filesystem path from a caller-controlled `id`/`avID` and read it without confining the result to the attribute-view storage directory (`DataDir/storage/av/`). On the load (file-exists) code path there is no boundary check, so an `avID` containing `../` segments escapes `storage/av/` and causes the kernel to read a `.json` file elsewhere in the workspace.\n\nThe endpoints require only `CheckAuth`, which the publish service's `RoleReader` token satisfies; when `Publish.Auth.Enable` is `false` the publish proxy uses the anonymous account, making the surface reachable with no credentials.\n\n### Details\n\nAffected endpoints (all gated by `CheckAuth` only, no `CheckAdminRole`):\n\n- `POST /api/av/renderAttributeView` &nbsp;→ `arg[\"id\"]`\n- `POST /api/av/getAttributeViewKeysByID` → `arg[\"avID\"]`\n- `POST /api/av/getAttributeViewKeys` &nbsp;→ `arg[\"id\"]`\n- `POST /api/av/getCurrentAttrViewImages` → `arg[\"id\"]`\n\nIn `model.RenderAttributeView` (`model/attribute_view_render.go`), the only identifier guard `ast.IsNodeIDPattern(avID)` sits **inside** the `if !filelock.IsExist(existPath)` (create) branch:\n\n```go\nexistPath = GetAttributeViewDataPath(avID)      // path built from avID, no check\nif !filelock.IsExist(existPath) {               // NOT-EXIST / CREATE branch\n    if !createIfNotExist {\n        return // NotFound\n    }\n    if !ast.IsNodeIDPattern(avID) {             // <-- ONLY id guard, create branch only\n        return ErrInvalidID\n    }\n    // ... create ...\n}\nattrView, err = av.ParseAttributeView(avID)     // LOAD runs unconditionally\n```\n\nWhen the traversal `avID` resolves to a file that already exists, the `!filelock.IsExist(...)` condition is `false`, the entire block (including the line with `ast.IsNodeIDPattern`) is skipped, and control falls straight through to `av.ParseAttributeView(avID)`. That function rebuilds the path via `filepath.Join(DataDir, \"storage\", \"av\", avID+\".json\")` and calls `filelock.ReadFile` with no `filepath.Rel` / `IsSubPath` / `..` rejection:\n\n```go\n// av.ParseAttributeView -> attributeViewDataPathByBox / GetAttributeViewDataPath\navJSONPath = filepath.Join(DataDir, \"storage\", \"av\", avID+\".json\")  // no boundary check\n// -> parseAttributeViewByPathInBox(avJSONPath, boxID)\ndata, _ = filelock.ReadFile(avJSONPath)                             // SINK\n```\n\n`filepath.Join` cleans the path but does **not** reject `..` segments, so it provides no containment. The three `getAttributeView*` endpoints call `ParseAttributeView` with no create branch at all, so they never even reach the `ast.IsNodeIDPattern` check same defect, same auth tier.\n\nThe root cause is that identifier validation is placed on a single code branch rather than confining the load to the AV base directory, so the load path reads a caller-controlled location.\n\n### PoC\n\n**Precondition:** publish mode enabled (default port `6808`); reachable by a `RoleReader` publish token, or anonymously when `Publish.Auth.Enable` is `false`.\n\nA request to `/api/av/renderAttributeView` with an `id` composed of `../` path segments that resolves to an existing `.json` file outside `DataDir/storage/av/` causes that file to be read and parsed instead of being rejected, because the identifier validation is only reached on the not-exist/create branch.\n\nI have withheld the exact encoded `id` value from this draft to avoid publishing a live traversal against internet-exposed publish instances. I'm happy to provide the precise value and a screenshot privately in this thread on request.\n\n### Impact\n\nAn authenticated publish `RoleReader` or an anonymous client when publish auth is disabled can cause the kernel to read `.json` files outside the attribute-view directory. Because the loaded file is unmarshalled into the attribute-view structure, the reliable primitives are:\n\n1. Disclosure of attribute-view (database) content from other scopes/notebooks the reader is not authorized to see.\n2. A `.json`-path existence oracle for arbitrary workspace locations.\n\nFiles not conforming to the AV schema are read but reflect little content, and the `.json` suffix is force-appended, so this is **not** a general arbitrary-file read. No admin role, CSRF token, or write permission is required.\n\n### Suggested fix\n\nValidate `avID` with `ast.IsNodeIDPattern` before path construction on **all** branches (move it ahead of `FindAttributeViewPath` / `GetAttributeViewDataPath`), or preferably, so every caller inherits it confine at the sink: in `attributeViewDataPathByBox` / `GetAttributeViewDataPath`, compute the joined path and reject it unless `filepath.Rel(avBaseDir, cleaned)` stays within `avBaseDir` (no leading `..`). Sink-side confinement also covers the three `getAttributeView*` endpoints that never reach the create-branch guard.","state":0,"publishedAt":"2026-09-03T20:34:12+00:00","modifiedAt":"2026-09-10T15:25:43.4607858+00:00","affected":[{"ecosystem":"Go","name":"github.com/siyuan-note/siyuan/kernel","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"0.0.0-20260720151813-0f5a0e7c67b0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"HIGH"}],"references":["https://github.com/siyuan-note/siyuan/security/advisories/GHSA-7hm9-v7vf-7g4w","https://nvd.nist.gov/vuln/detail/CVE-2026-69086","https://github.com/siyuan-note/siyuan","https://www.vulncheck.com/advisories/siyuan-before-path-traversal-via-unvalidated-avid"],"sourceUrl":"https://github.com/advisories/GHSA-7hm9-v7vf-7g4w","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-7hm9-v7vf-7g4w","identifiers":["GHSA-7hm9-v7vf-7g4w","CVE-2026-69086","GO-2026-6373"]},"retained":false,"historicalAffected":[]},{"revision":"b53ca277765d4567a22a0fc07b5e1120","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GO-2026-6373","aliases":["CVE-2026-69086","GHSA-7hm9-v7vf-7g4w"],"title":"SiYuan: Path Traversal via unvalidated avID in RenderAttributeView/AV read endpoints : reader-reachable cross-scope attribute-view disclosure in github.com/siyuan-note/siyuan/kernel","description":"SiYuan: Path Traversal via unvalidated avID in RenderAttributeView/AV read endpoints : reader-reachable cross-scope attribute-view disclosure in github.com/siyuan-note/siyuan/kernel","state":0,"publishedAt":"2026-09-10T14:48:42+00:00","modifiedAt":"2026-09-10T15:15:12.9131056+00:00","affected":[{"ecosystem":"Go","name":"github.com/siyuan-note/siyuan/kernel","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"0.0.0-20260720151813-0f5a0e7c67b0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[],"references":["https://github.com/siyuan-note/siyuan/security/advisories/GHSA-7hm9-v7vf-7g4w","https://nvd.nist.gov/vuln/detail/CVE-2026-69086","https://www.vulncheck.com/advisories/siyuan-before-path-traversal-via-unvalidated-avid"],"sourceUrl":"https://osv.dev/vulnerability/GO-2026-6373","license":"OSV · upstream source license applies","key":"osv:GO-2026-6373","identifiers":["GO-2026-6373","CVE-2026-69086","GHSA-7hm9-v7vf-7g4w"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-10-26T17:37:18.9351244+00:00","complete":true,"records":1756,"lastAttemptAt":"2026-10-26T17:37:18.9351244+00:00","lastSuccessAt":"2026-10-26T17:37:19.151471+00:00","error":null,"lastVerifiedAt":"2026-10-26T17:37:19.1514719+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-5ba1945314e042c2ced14b33f3680fa71692812d925544312b218f5eb8a26e71-d6f206810bfc698eadf8f28407d530f4767f368cd89e94211e8dccb68eba0455","complete":true,"records":414339,"lastAttemptAt":"2026-10-26T17:35:34.9653803+00:00","lastSuccessAt":"2026-10-26T17:35:34.8568888+00:00","error":null,"lastVerifiedAt":"2026-10-26T17:35:34.9653803+00:00","snapshotPublishedAt":"2026-10-26T17:28:56+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-43321610382942b8ad8c85917eab1546","complete":false,"records":4735,"lastAttemptAt":"2026-10-26T17:37:46.9178053+00:00","lastSuccessAt":"2026-10-24T23:18:49.862+00:00","error":"InvalidDataException","lastVerifiedAt":"2026-10-24T23:18:49.862+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":2564,"expectedIdentifiers":13477},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-10-26T17:37:18.9351244+00:00","complete":true,"records":1093,"lastAttemptAt":"2026-10-26T17:37:18.9351244+00:00","lastSuccessAt":"2026-10-26T17:37:19.1522283+00:00","error":null,"lastVerifiedAt":"2026-10-26T17:37:19.1522304+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-141ff4fb146e4923a19e7481870bbe2d","complete":false,"records":13416,"lastAttemptAt":"2026-10-26T17:37:44.6767196+00:00","lastSuccessAt":"2026-10-26T17:37:44.673+00:00","error":null,"lastVerifiedAt":"2026-10-26T17:37:44.673+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13077,"expectedIdentifiers":13477},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-c3121b113ecd88f1c92ccfa0ec9757ddc8386e4c12afd2597450b815744f800a","complete":true,"records":9779,"lastAttemptAt":"2026-10-26T17:37:18.6945274+00:00","lastSuccessAt":"2026-10-26T15:37:14.3083004+00:00","error":null,"lastVerifiedAt":"2026-10-26T17:37:18.6945274+00:00","snapshotPublishedAt":"2026-10-26T14:48:41+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-bad5d31e7f6a5e3d338e11d8789069b63620a403f927730769688b42f768e4f6","complete":true,"records":1965,"lastAttemptAt":"2026-10-26T17:35:35.1091889+00:00","lastSuccessAt":"2026-10-26T16:35:43.1460623+00:00","error":null,"lastVerifiedAt":"2026-10-26T17:35:35.1091889+00:00","snapshotPublishedAt":"2026-10-26T16:18:29+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-a393d8fe0ae8408f3e4cab413b76047090c8e4a3c0a186c79edf33c9a3d3af95","complete":true,"records":2995,"lastAttemptAt":"2026-10-26T17:37:18.8871755+00:00","lastSuccessAt":"2026-10-26T14:35:47.9640893+00:00","error":null,"lastVerifiedAt":"2026-10-26T17:37:18.8871755+00:00","snapshotPublishedAt":"2026-10-26T14:18:55+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-278d5002a4c49eb0a53aa603d1ea0cbe27ac563f4fab7dbdf3bbdb9c900730cf","complete":true,"records":230811,"lastAttemptAt":"2026-10-26T17:37:18.5499294+00:00","lastSuccessAt":"2026-10-26T17:37:17.1540989+00:00","error":null,"lastVerifiedAt":"2026-10-26T17:37:18.5499294+00:00","snapshotPublishedAt":"2026-10-26T16:48:35+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null}]}