# SiYuan: Unauthenticated SQL execution and REGEXP injection via fullTextSearchAssetContent (publish mode): reader-reachable raw SQL (method 2) and unescaped REGEXP (method 3) on read-write asset-content DB

SiYuan's fullTextSearchAssetContent endpoint lets publish readers run raw SQL or break out of an unescaped REGEXP clause on the read-write asset-content DB, leaking cross-notebook data.

- Payout: Research
- Severity: critical
- Program: SiYuan
- Found by (vendor credit): Shirshakhtml
- Found by: Shirshakhtml
- Disclosed: 2026-09-03
- CVE: CVE-2026-69083
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-fph3-ghq9-vw66
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-fph3-ghq9-vw66
- Tags: area:web domain:web impact:data-leak impact:integrity kind:research platform:ghsa sev:critical tech:go technique:source-review vuln:access-control vuln:auth-bypass vuln:sqli

**Target:** POST /api/search/fullTextSearchAssetContent (publish-mode search API)
**Root cause:** The asset-content search handler lacks the admin guard its block-search sibling has, passes client SQL straight to a read-write DB handle with no single-statement/read-only check, and builds a REGEXP clause by concatenation without escaping single quotes.
**Steps:**
1. Create notebook and doc with secret body via admin token: `POST /api/notebook/createNotebook` then `POST /api/filetree/createDocWithMd` with `{"notebook":"BOX","path":"/f3-secret","markdown":"## SecretSection\n\nUNIQUE_MARKER_99 hidden body text"}`
2. Fetch heading block id via admin `POST /api/query/sql` with `{"stmt":"SELECT id,type,content FROM blocks WHERE type='h'"}`
3. Disable publishing for the doc: `POST /api/filetree/setPublishAccess` with `{"id":"DOC","visible":false,"password":"","disable":true}`
4. As anonymous reader on publish port 6808, send `POST /api/search/fullTextSearchAssetContent` with `method` 2 and a raw SQL `query`, or `method` 3 with a `query` containing a single quote to break out of the REGEXP literal
5. Observe cross-notebook asset-content rows returned; stacking/ATTACH reachable via the read-write handle
**How found:** Compared the asset-content search handler against its block-search sibling: noticed fullTextSearchBlock rejects method 2 for non-admins while fullTextSearchAssetContent does not, and that fieldRegexp escapes single quotes but assetContentFieldRegexp omits the ReplaceAll step.
**Exploitation:** Anonymous or RoleReader sends method 2 with an arbitrary SQL statement (or method 3 with a quote-breakout REGEXP expression) to the publish endpoint; the statement executes on the read-write asset-content DB, allowing cross-notebook read disclosure, content modification via stacked statements, and ATTACH-reachable file access. No admin role needed.
**Escalation:** Read-write handle plus statement stacking and ATTACH extends read disclosure to DB modification and attached-file access; code execution not reachable in default build (no load_extension).
**Insight:** When a codebase has parallel search builders (block vs asset), diff them line by line: missing admin guards and missing quote-escaping in the twin are high-yield. Also check whether reader-reachable DB handles set `_query_only`/`mode=ro`.

