Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 274/275 feeds/APIs · 469/469 docs · 8/9 advisories · checked 12:06 UTC Customize Public modeDiscuss ChangeIntel on Discord

SiYuan before v3.8.1 SSRF via DNS-Rebinding TOCTOU

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2026-82234

Published

SiYuan versions before v3.8.1 contain a server-side request forgery vulnerability in the http_request and web_fetch agent tools that perform DNS resolution only at guard time without validating the connect-time resolution. Attackers can use DNS rebinding to answer the guard resolution with a public IP and the connect resolution with a private or metadata IP, bypassing the SSRF defense to access cloud instance metadata and internal services.

Source published
28 Aug 2026 10:49:24 UTC
Source modified
28 Aug 2026 16:10:07 UTC
Observed here
23 Oct 2026 15:48:27 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · 8.4 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:L/VA:N/SC:H/SI:L/SA:N

CVSS 3.1 · 8.2 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N

euvd · EUVD-2026-67686

Published

SiYuan versions before v3.8.1 contain a server-side request forgery vulnerability in the http_request and web_fetch agent tools that perform DNS resolution only at guard time without validating the connect-time resolution. Attackers can use DNS rebinding to answer the guard resolution with a public IP and the connect resolution with a private or metadata IP, bypassing the SSRF defense to access cloud instance metadata and internal services.

EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.

Original publisher date fields

datePublished: Aug 28, 2026, 10:49:24 AM

dateUpdated: Aug 28, 2026, 4:10:07 PM

Source published
Aug 28, 2026, 10:49:24 AM (timezone not stated)
Source modified
Aug 28, 2026, 4:10:07 PM (timezone not stated)
Observed here
9 Nov 2026 15:15:33 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 4.0 · 8.4 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:L/VA:N/SC:H/SI:L/SA:N

nvd · CVE-2026-82234

Published

SiYuan versions before v3.8.1 contain a server-side request forgery vulnerability in the http_request and web_fetch agent tools that perform DNS resolution only at guard time without validating the connect-time resolution. Attackers can use DNS rebinding to answer the guard resolution with a public IP and the connect resolution with a private or metadata IP, bypassing the SSRF defense to access cloud instance metadata and internal services.

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.

Source analysis status: Deferred

Weakness classifications: CWE-918

Original publisher date fields

published: 2026-08-28T12:16:33.120

lastModified: 2026-08-28T20:20:15.483

Source published
28 Aug 2026 12:16:33 UTC
Source modified
28 Aug 2026 20:20:15 UTC
Observed here
25 Oct 2026 16:19:10 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · [email protected] · Secondary · 8.4 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:L/VA:N/SC:H/SI:L/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

CVSS 3.1 · [email protected] · Secondary · 8.2 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N

osv · GHSA-x8gv-g2g3-65fj

Published

# Security Advisory — SiYuan Agent Tools SSRF via DNS-Rebinding TOCTOU (Bypass of `CheckHostSSRF`) | Field | Value | |---|---| | **Disclosed by** | joysinleung (`[email protected]`) | | **Report date** | 2026-08-13 | | **Product** | SiYuan (思源笔记) — `siyuan-note/siyuan` | | **Go module** | `github.com/siyuan-note/siyuan/kernel` | | **Affected versions** | `<= 3.8.0` (latest release at report time; dynamically verified on v3.8.0) | | **Patched versions** | 3.8.1 | | **Component** | `kernel/util/httprequest.go` (`CheckHostSSRF`), `kernel/mcp/tools/http_request.go`, `kernel/util/webfetch.go`, `kernel/util/net.go` (`SSRFSafeDialer`) | | **Relationship to prior advisory** | **Incomplete-fix variant of GHSA-rg26-cg95-gq6p** (SSRF main-vector remediation). See §Relationship. | | **EPSS (exploitation probability)** | Low–Moderate. Requires the attacker to influence an AI Agent / MCP client into fetching an attacker-controlled domain (prompt-injection scenario documented by the tool itself). | | **KEV (CISA Known Exploited)** | No (not listed in CISA KEV at report time). | | **Default-config reachable** | **Yes** — exploitable under *both* `SafeMode` on and off; only requires the agent `http_request` / `web_fetch` tool to be reachable (default AI tooling). | --- ## Summary SiYuan's AI Agent tools `http_request` (`util.HTTPRequest`) and `web_fetch` (`util.WebFetch`) are the only SSRF gate for outbound requests from the kernel. That gate is `CheckHostSSRF`, which performs a **single DNS resolution at guard time** and checks whether any returned IP is private/loopback/link-local. The actual connection, however, performs a **second, independent DNS resolution** through the default `net.Dialer` — and **no connect-time private-IP check is mounted** on this path. Because the two resolutions are not pinned to the same result, an attacker-controlled domain can answer the guard-resolution with a **public IP** (passing `CheckHostSSRF`) and the connect-resolution with a **private/loopback/metadata IP** (e.g. `169.254.169.254`). This is a classic **DNS-rebinding TOCTOU** that bypasses the SSRF defense entirely. It reaches cloud instance metadata and internal services that the guard was specifically added to block. ## Relationship to Prior Advisories - **GHSA-rg26-cg95-gq6p** remediated the SSRF *main vector* by adding `CheckHostSSRF` (parse-time) **and** `SSRFSafeDialer` (connect-time). However, **the agent tool paths (`http_request` / `web_fetch`) only received the parse-time half**: they call `CheckHostSSRF` but then connect via `httpclient.NewBrowserRequest()`, whose transport does **not** mount `SSRFSafeDialer`. Even where `SSRFSafeDialer` *is* mounted, it only blocks private IPs when `SafeMode == true` (default false), so it would not help here regardless. The sibling path `openai.go:generatedImageDialer` *does* mount a connect-time `Control` hook (blocking private/loopback/link-local/100.64/198.18), proving the project knows the technique — the agent path is a clear omission. We report this as an **incomplete-fix variant** with a concrete v3.8.0 reproduction. - **CVE-2026-32110** (GHSA-56cv-c5p2-j2wg) covered the older `forwardProxy` endpoint and is unrelated to the agent tool path. ## Affected Version **Dynamically verified on v3.8.0** (tag `v3.8.0`, commit `251596fc0`). A process-level DNS hijack was installed so that the attacker domain `rebind.local` returns a public IP (`203.0.113.1`) on odd (guard) resolutions and `127.0.0.1` on even (connect) resolutions; a loopback "victim" service returned `F9_REBIND_PROOF=reached-internal-only-service-via-TOCTOU`. Both `util.HTTPRequest("GET", "http://rebind.local:<port>/secret")` and `util.WebFetch(...)` returned the internal-only proof body, while `CheckHostSSRF("127.0.0.1")` directly blocked and the legit public domain `pub.local` passed — confirming the guard passed but the connection hit the internal address. All versions `<= 3.8.0` are affected. ## Component - `kernel/util/httprequest.go:42` `CheckHostSSRF` — single `net.LookupIP` + `isPrivateIP` at guard time only. - `kernel/mcp/tools/http_request.go:90` → `util.HTTPRequest`; `kernel/util/webfetch.go:50` → `CheckHostSSRF` + `httpclient.NewBrowserRequest()`. - `github.com/siyuan-note/httpclient` `client.go:92` `NewBrowserRequest` uses the default `http.Transport` → default `net.Dialer` with **no `SSRFSafeDialer`**. - `kernel/util/net.go:151` `SSRFSafeDialer` exists but is (a) not mounted on the agent path and (b) only active under `SafeMode`. - Correctly-defended sibling: `kernel/util/openai.go:829` `generatedImageDialer` mounts a connect-time `Control` hook. ## Attack Vector **Network + AI Agent.** The `url` of `http_request` / `web_fetch` is fully controlled by the agent / MCP client. In SiYuan's documented red-team scenario ("prompt-inject the agent → induce it to visit an attacker domain"), the attacker needs only a rebinding domain (own authoritative DNS, first answer public, later `169.254.169.254` / internal). No auth, no special position beyond prompting the agent. Real targets: cloud metadata `169.254.169.254` (IMDSv1 IAM creds) and same-host/internal unauthenticated services. ## Proof of Concept ``` # Attacker authoritative DNS for rebind.local: # odd query (guard) -> 203.0.113.1 (public, passes CheckHostSSRF) # even query (dial) -> 127.0.0.1 (loopback internal victim) # # Directly invoke the real agent-tool functions (v3.8.0 code path): util.HTTPRequest("GET", "http://rebind.local:15353/secret", ...) util.WebFetch("http://rebind.local:15353/secret", ...) # Result (evidence): # body = "F9_REBIND_PROOF=reached-internal-only-service-via-TOCTOU" # Negative control: CheckHostSSRF("127.0.0.1") -> blocked. # Positive control: CheckHostSSRF("pub.local") -> 203.0.113.1, allowed. ``` The loopback victim is a faithful stand-in for `169.254.169.254` / any internal address: the guard allowed a public IP while the connection reached a private one. ## Impact Confidentiality breach via SSRF: an attacker who can steer the agent can read cloud instance metadata (IAM temporary credentials), internal service responses, and anything reachable from the SiYuan kernel's network position. Scope is changed (`S:C`) because the kernel often runs with cloud-instance privileges. Exploitable under default config (SafeMode on or off). ## Scope Reachable whenever the agent `http_request` / `web_fetch` tool is usable (default AI tooling). Independent of Publish/auth configuration. Not gated by `SafeMode`. ## Remediation 1. **Connect-time enforcement (preferred)**: mount `SSRFSafeDialer` (or a dedicated always-on private-IP `Control` hook) on the transport used by `http_request` / `web_fetch`, independent of `SafeMode` — matching the already-correct `generatedImageDialer`. 2. **Pin resolution**: after `CheckHostSSRF` passes, reuse the *same* resolved IP for the connection (or short-TTL cache) so guard and dial cannot diverge. 3. **Minimum change**: replace `httpclient.NewBrowserRequest()` in `http_request.go` / `webfetch.go` with a custom client whose `DialContext` is `util.SSRFSafeDialer(timeout).DialContext` (not `SafeMode`-gated). > Note: patch authored against v3.8.0 source; regression-tested in the researcher's environment for the PoC path but not compiled into a full SiYuan release build. Provided for the maintainer to validate in CI. --- ## Appendix: Suggested Patch (F9) ```diff diff --git a/kernel/util/httprequest.go b/kernel/util/httprequest.go index aaa..bbb 100644 --- a/kernel/util/httprequest.go +++ b/kernel/util/httprequest.go @@ -40,6 +40,18 @@ func CheckHostSSRF(host string) error { return nil } +// SSRFSafeClient returns an *http.Client whose transport enforces the +// private/loopback/link-local IP block at CONNECT time (independent of SafeMode), +// closing the DNS-rebinding TOCTOU left by parse-time-only CheckHostSSRF. +func SSRFSafeClient(timeout time.Duration) *http.Client { + return &http.Client{ + Timeout: timeout, + Transport: &http.Transport{ + DialContext: util.SSRFSafeDialer(timeout).DialContext, + }, + } +} + diff --git a/kernel/mcp/tools/http_request.go b/kernel/mcp/tools/http_request.go index ccc..ddd 100644 --- a/kernel/mcp/tools/http_request.go +++ b/kernel/mcp/tools/http_request.go @@ -90,7 +90,7 @@ func httpRequest(args map[string]any) (CallToolResult, error) { if serr := util.CheckHostSSRF(u.Hostname()); serr != nil { return CallToolResult{}, serr } - resp, err := httpclient.NewBrowserRequest().Get(rawURL) + resp, err := util.SSRFSafeClient(30 * time.Second).Get(rawURL) ... } diff --git a/kernel/util/webfetch.go b/kernel/util/webfetch.go index eee..fff 100644 --- a/kernel/util/webfetch.go +++ b/kernel/util/webfetch.go @@ -50,7 +50,7 @@ func WebFetch(rawURL string, ...) (string, error) { if serr := util.CheckHostSSRF(u.Hostname()); serr != nil { return "", serr } - resp, err := httpclient.NewBrowserRequest().Get(rawURL) + resp, err := util.SSRFSafeClient(30 * time.Second).Get(rawURL) ... } ```

Source published
2 Oct 2026 23:17:16 UTC
Source modified
7 Oct 2026 17:55:46 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N

Publisher rating · HIGH

osv · GO-2026-6657

Published

SiYuan Agent Tools SSRF via DNS-Rebinding TOCTOU (Bypass of CheckHostSSRF) in github.com/siyuan-note/siyuan/kernel

Source published
7 Oct 2026 14:10:14 UTC
Source modified
7 Oct 2026 17:55:46 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
OSV · upstream source license applies

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · OSV · upstream source license applies. Source text is retained; field grouping and change labels are provided by ChangeIntel.

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 11 Nov 12:06 UTC · 274 of 275 readable · 273 fully read · documentation 469/469 current