# SiYuan: Embedded (transclusion) block content is returned without publish-access filtering, leaking private and password-protected document content to anonymous readers

SiYuan's getBlockDOMWithEmbed endpoints gate only the requested block, inlining embed-query results from hidden and password-protected documents to anonymous publish readers.

- Payout: Research
- Severity: high
- Program: SiYuan
- Found by (vendor credit): Shirshakhtml
- Found by: Shirshakhtml
- Disclosed: 2026-09-04
- CVE: CVE-2026-72795
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-h6w7-xxcf-w2mq
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-h6w7-xxcf-w2mq
- Tags: area:web domain:web impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:go technique:source-review vuln:access-control vuln:auth-bypass vuln:info-disclosure

**Target:** SiYuan kernel API (/api/block/getBlockDOMWithEmbed, getBlockDOMsWithEmbed) in publish mode
**Root cause:** resolveEmbedContentInBox executes embed SQL and inlines matched block content without any publishAccess filtering; only the top-level requested block is checked against publish access.
**Steps:**
1. Enable publish mode (default port 6808); anonymous if Publish.Auth.Enable is false, else use any publish RoleReader account.
2. Ensure a published document contains an embed query matching blocks in non-published or password-protected documents.
3. `POST http://127.0.0.1:6808/api/block/getBlockDOMWithEmbed` with `{"id":"<id of a published block containing an embed query>"}`
4. Observe returned DOM embed-content attributes carrying content HTML of inaccessible blocks.
5. Differential: `POST /api/search/getEmbedBlock` with `{"stmt":"<the same embed query>"}` returns filtered results via FilterEmbedBlocksByPublishAccess.
6. Plural route `POST /api/block/getBlockDOMsWithEmbed` with `{"ids":["<published block>"]}` behaves identically.
**How found:** Compared the guarded sibling getEmbedBlock (which applies FilterEmbedBlocksByPublishAccess for reader roles) against the DOM-with-embed path; traced getBlockDOMWithEmbed → GetBlockDOMsWithEmbedInBox → resolveEmbedContentInBox and found no publishAccess parameter or filtering calls in that function.
**Exploitation:** A reader requests an already-published block containing an embed query; the server resolves the query and inlines matched block content into the response, disclosing private/hidden/password-protected document content passively during normal viewing.
**Insight:** When an endpoint returns derived/aggregated data (embed queries, joins, expansions), check whether the authorization gate covers only the requested object or also the resolved children; diff against sibling endpoints returning the same data class to spot missing filters.

