# SiYuan: Authorization Bypass Allows Arbitrary SQL Execution via Search API

SiYuan's fullTextSearchBlock endpoint with method=2 passes raw SQL to SQLite without admin/readonly checks, letting any Reader execute arbitrary SQL.

- Payout: Research
- Severity: critical
- Program: SiYuan
- Found by: iconnnjka
- Disclosed: 2026-03-16
- CVE: CVE-2026-32767
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-j7wh-x834-p3r7
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-j7wh-x834-p3r7
- Tags: area:web domain:web impact:data-leak impact:dos impact:integrity kind:research platform:ghsa sev:critical tech:go technique:source-review vuln:access-control vuln:auth-bypass vuln:sqli

**Target:** /api/search/fullTextSearchBlock endpoint (Go/Gin, SQLite backend)
**Root cause:** The search endpoint only applies CheckAuth, omitting CheckAdminRole and CheckReadonly that guard /api/query/sql; when method=2 the raw query string is passed to searchBySQL and executed via db.Query, which runs any SQL statement.
**Steps:**
1. Authenticate as any role including Reader to obtain a token.
2. POST to `/api/search/fullTextSearchBlock` with body `{"method": 2, "query": "SELECT * FROM blocks LIMIT 100"}` to read data.
3. Send `{"method": 2, "query": "DELETE FROM blocks"}` to delete data.
4. Send `{"method": 2, "query": "DROP TABLE blocks"}` to drop tables.
5. Compare: same token against `/api/query/sql` returns 403.
**How found:** Code review comparing router middleware: noticed /api/query/sql chains CheckAdminRole and CheckReadonly while /api/search/fullTextSearchBlock only has CheckAuth, then traced method=2 through searchBySQL to raw db.Query execution.
**Exploitation:** Any authenticated user, including Reader role, sends a POST with method=2 and an arbitrary SQL statement in the query field; the statement is parsed, falls through to selectBlocksRawStmt, and executed via db.Query, allowing read, modify, delete, or drop of database contents.
**Insight:** When an app exposes a dedicated privileged endpoint (SQL query) with admin/readonly middleware, grep sibling endpoints for alternate code paths that reach the same dangerous sink (raw db.Query) without those middleware — search/filter/export APIs often reuse the query engine.

## Proof of concept (copied exactly from the original report)

**Reader token executes arbitrary SELECT via search API**

```
curl -X POST http://<target>:6806/api/search/fullTextSearchBlock \
  -H "Content-Type: application/json" \
  -H "Authorization: Token <reader_token>" \
  -d '{"method": 2, "query": "SELECT * FROM blocks LIMIT 100"}'
```

