Description
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.
Published: 2026-08-20
Score: 6.3 Medium
EPSS: < 1% Very Low
KEV: No
Impact: n/a
Action: n/a
AI Analysis

Impact

The vulnerability exists in the POST /api/provider-nodes/validate endpoint of 9router. It accepts a caller‑supplied baseUrl and performs a server‑side HTTP request after running a guard that only compares host names, never resolves DNS, ignores redirects, and contains an unreachable branch for IPv4‑mapped IPv6 addresses. As a result, every IPv4‑mapped literal, such as http://[::ffff:127.0.0.1]/, passes the filter and reaches the loopback or link‑local metadata space, exposing internal hosts. Additionally, a body from upstream responses that are not 2xx, 401, or 403 is truncated to 200 bytes and returned to the caller, leaking the beginning of internal responses. The caller’s apiKey is also forwarded to the internal target as a Bearer token, providing a potential credential‑stealing vector.

Affected Systems

The affected product is decolua 9router, specifically any instance that exposes the /api/provider-nodes/validate API. The vulnerability is present in all versions of 9router that have not applied the fix from the referenced pull request, and it can be exploited when the endpoint is enabled, whether requireLogin is disabled or a dashboard session is used.

Risk and Exploitability

The CVSS score of 6.3 indicates a moderate impact. EPSS is not currently available and the vulnerability is not listed in the CISA KEV catalog. The attack can be carried out by any user able to send a POST to the endpoint; if requireLogin is disabled, no authentication is required, otherwise an authenticated session is sufficient. Because the guard fails for IPv4‑mapped addresses, an attacker can issue requests to 127.0.0.1, 169.254.0.0/16, or other internal ranges, enabling internal reconnaissance, data exfiltration, or credential leakage via the forwarded apiKey. The vulnerability is relatively straightforward to exploit once the endpoint is reachable.

Generated by OpenCVE AI on August 21, 2026 at 00:51 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Update 9router to a patched release that validates IPv4‑mapped IPv6 addresses and refuses local network requests (see the pull request that closes this flaw).
  • If an update is not possible, disable or restrict access to the /api/provider-nodes/validate endpoint, for example by enabling requireLogin and allowing only trusted administrators to call it.
  • Block outbound traffic from the 9router process to internal IP ranges such as 127.0.0.0/8, 169.254.0.0/16, 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 using firewall rules or container network policies.

Generated by OpenCVE AI on August 21, 2026 at 00:51 UTC.

Tracking

Sign in to view the affected projects.

Advisories

No advisories yet.

History

Tue, 25 Aug 2026 16:30:00 +0000

Type Values Removed Values Added
Metrics ssvc

{'options': {'Automatable': 'no', 'Exploitation': 'poc', 'Technical Impact': 'partial'}, 'version': '2.0.3'}


Thu, 20 Aug 2026 23:00:00 +0000

Type Values Removed Values Added
First Time appeared Decolua
Decolua 9router
Vendors & Products Decolua
Decolua 9router

Thu, 20 Aug 2026 21:45:00 +0000

Type Values Removed Values Added
Description 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.
Title 9router Server-Side Request Forgery via /api/provider-nodes/validate Because the IPv4-Mapped IPv6 Denylist Check Is Unreachable
Weaknesses CWE-184
CWE-918
References
Metrics cvssV3_1

{'score': 8.5, 'vector': 'CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N'}

cvssV4_0

{'score': 6.3, 'vector': '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'}


cve-icon MITRE

Status: PUBLISHED

Assigner: VulnCheck

Published:

Updated: 2026-08-25T15:27:22.100Z

Reserved: 2026-08-10T15:16:31.372Z

Link: CVE-2026-72860

cve-icon Vulnrichment

Updated: 2026-08-25T15:27:17.003Z

cve-icon NVD

Status : Received

Published: 2026-08-20T22:18:05.787

Modified: 2026-08-25T16:17:25.880

Link: CVE-2026-72860

cve-icon Redhat

No data.

cve-icon OpenCVE Enrichment

Updated: 2026-08-21T01:00:04Z

Weaknesses
  • CWE-184

    Incomplete List of Disallowed Inputs

  • CWE-918

    Server-Side Request Forgery (SSRF)