CVE-2026-72860
9router Server-Side Request Forgery via /api/provider-nodes/validate Because the IPv4-Mapped IPv6 Denylist Check Is Unreachable
The POST /api/provider-nodes/validate route in 9router takes a caller-supplied baseUrl and issues server-side HTTP requests to it, guarding the destination with assertPublicUrl from src/shared/utils/ssrfGuard.js. That guard compares hostname strings only: it resolves no DNS, does not revalidate after a redirect, and its IPv4-mapped IPv6 branch is unreachable. The branch matches ^::ffff:(\d+\.\d+\.\d+\.\d+)$, but the WHATWG URL parser canonicalizes such literals to hextets before the guard runs, so new URL("http://[::ffff:127.0.0.1]/").hostname yields [::ffff:7f00:1] and the pattern is tested against a string it is never handed. Every IPv4-mapped address therefore passes, and http://[::ffff:7f00:1] and http://[::ffff:a9fe:a9fe] reach loopback and link-local metadata addresses; a hostname whose A record points at an internal address passes as well because no resolution occurs. In the custom-embedding branch the upstream response body is truncated to 200 bytes and returned to the caller whenever the upstream status is neither 2xx nor 401 nor 403, which discloses the beginning of internal responses, and the other validation types remain usable for blind internal port scanning through status and timing differences. The caller-supplied apiKey is forwarded to the internal destination as an Authorization Bearer header. A dashboard session is required by default, and none is required when requireLogin is disabled.
Fixes and workarounds
Fix
The reporting source identifies this reference as a patch. Check the advisory for affected versions and supported release branches.
Source: CNA: VulnCheckAffected products and versions
| Product | Versions | Authority |
|---|---|---|
| 9router decolua 9router
npm |
≥ 0; ≤ 0.5.55 (affected, custom)
Other versions: unaffected |
CNA: VulnCheck |
Version ranges are source assertions. Check the vendor advisory and your installed configuration before determining exposure.
CVSS assessments
| Version / score | Vector | Authority |
|---|---|---|
| 3.1 / 8.5 high |
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N | CNA: VulnCheck |
| 4.0 / 6.3 medium |
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:N | CNA: VulnCheck |
Exploit evidence
- https://github.com/decolua/9router/issues/3293
exploit · ADP: CISA-ADP
References
- https://github.com/decolua/9router/issues/3293CNA: VulnCheck · issue-tracking
- https://github.com/decolua/9router/blob/master/src/shared/utils/ssrfGuard.jsCNA: VulnCheck · technical-description
- https://github.com/decolua/9router/blob/master/src/app/api/provider-nodes/validate/route.jsCNA: VulnCheck · technical-description
- https://github.com/decolua/9router/pull/3370CNA: VulnCheck · issue-tracking, patch
- https://github.com/decolua/9routerCNA: VulnCheck · product
- https://www.vulncheck.com/advisories/9router-server-side-request-forgery-via-api-provider-nodes-validate-because-the-ipv4-mapped-ipv6-denylist-check-is-unreachableCNA: VulnCheck · third-party-advisory
- https://github.com/decolua/9router/issues/3293ADP: CISA-ADP · exploit
For agents and automation
Read public disclosures for free as Markdown or JSON. Compatible browsers also expose native WebMCP tools to search disclosures, read this page, and discover API access.
Use the ontology-linked Cyber API with x402 pay per request, or a Y2 Pro or Elite API key with the intel:cyber scope.
Endpoints and access details
https://api.y2.dev/api/v2/cyber/cveshttps://api.y2.dev/api/v2/cyber/cves/{cveId}
A workspace owner or admin can create a Pro or Elite API key. Send Authorization: Bearer <Y2_API_KEY> from your trusted agent runtime.
For x402, omit Authorization and read the HTTP 402 payment challenge before signing a retry. Public browser tools do not make payments.