high · 8.6CVE-2026-56677Aug 17, 2026

CVE-2026-56677: 9router Unauthenticated SSRF via OIDC Test Endpoint

Shubham Kandhare
Security Engagement Manager, SecureLayer7

Any unauthenticated user can point 9router's OIDC test endpoint at an internal IP address, turning the dashboard server into a proxy for scanning and reading private network services.

Package9router
Ecosystemnpm
Affected<= 0.5.4
CVE-2026-56677: 9router Unauthenticated SSRF via OIDC Test Endpoint

The problem

The POST /api/auth/oidc/test endpoint accepts a user-supplied issuerUrl and immediately issues an outbound fetch to that URL with no authentication middleware and no IP blocklist check.

An anonymous remote attacker can target loopback or RFC-1918 addresses (127.0.0.1, 10.0.0.0/8, 192.168.0.0/16). Closed or non-HTTP ports leak timing and JSON parse errors that confirm the TCP handshake succeeded. Open ports serving valid JSON reflect internal data back to the caller in the 200 OK body, enabling full read-SSRF.

Proof of concept

A working proof-of-concept for CVE-2026-56677 in 9router, with the exact payload below.

http
POST /api/auth/oidc/test HTTP/1.1
Host: <9router-host>:3000
Content-Type: application/json
Content-Length: 54

{
  "issuerUrl": "http://127.0.0.1:80",
  "clientId": "probe_only"
}

The route handler in src/app/api/auth/oidc/test/route.js calls fetchOidcDiscovery(issuerUrl) directly, which expands to fetch(${issuerUrl}/.well-known/openid-configuration). No session token is required because /api/auth/oidc/test is absent from the Next.js middleware matcher list in src/proxy.js, so dashboardGuard never runs.

The root causes are CWE-306 (missing authentication on a critical function) and CWE-918 (SSRF). When a closed port responds with non-JSON, the app leaks the raw parse error to the caller, confirming the outbound connection. When a port returns a valid OpenID configuration structure, the parsed fields (authorizationEndpoint, tokenEndpoint, jwksUri) are reflected verbatim in the 200 response.

The fix adds authentication middleware to the route and resolves the destination hostname server-side before fetching, rejecting loopback and private-range IPs and enforcing the https:// scheme.

The fix

Upgrade 9router to version 0.5.5 or later. The patch (1) wraps /api/auth/oidc/test in the same dashboardGuard session middleware used by other protected routes, and (2) validates that the resolved IP of issuerUrl is not a loopback or private-range address and that the scheme is https before any outbound request is made.

Reporter not attributed.

References: [1][2]

Related research