Votre programme voit-il ce que voient les attaquants ?

La plupart des programmes de sécurité sont plus avancés en découverte qu'en validation. L'Exposure Maturity Model identifie précisément la dimension qui freine votre programme.

No items found.
Alertes de vulnérabilité
-
5
mins read
-
May 13, 2026

Next.js WebSocket SSRF: Unauthenticated Access to Internal Resources: CVE-2026-44578

-
- -
Next.js WebSocket SSRF: Unauthenticated Access to Internal Resources: CVE-2026-44578

On May 11, 2026, Vercel published the GHSA-c4j6-fc7j-m34r and released Next.js 15.5.16 and 16.2.5, fixing CVE-2026-44578: a server-side request forgery vulnerability in the WebSocket upgrade handler that affects all self-hosted Next.js deployments from 13.4.13 onward. The flaw lets an unauthenticated attacker, with a single crafted HTTP request, cause the Next.js process to issue an internal HTTP GET to any host reachable from the server on port 80 (cloud metadata services, administrative panels, internal APIs) and read the response. Sampling of directly-exposed Shodan-indexed Next.js hosts on the default port suggests approximately 79,000 instances are exploitable today. Vercel-hosted applications are not affected.

The vulnerability is rated High severity (CVSS 8.6) and requires immediate patching to version 15.5.16 or 16.2.5. Organizations running self-hosted Next.js without these patches should implement reverse-proxy-based mitigations immediately, as the attack surface includes any publicly reachable Next.js instance running the built-in Node.js server. WebSocket upgrade handling is part of the core HTTP/1.1 router and cannot be disabled without code changes.

Technical overview

  • Vulnerability: Server-side request forgery via WebSocket upgrade handler
  • CVE: CVE-2026-44578
  • GHSA: GHSA-c4j6-fc7j-m34r
  • Severity: High (CVSS 8.6, `AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N`)
  • Impact: Unauthenticated GET-only SSRF to any host on port 80 reachable from the server; cloud metadata exposure
  • Affected versions: Next.js 13.4.13+, 14.x, 15.x <15.5.16, 16.0.0 <16.2.5 (self-hosted only)
  • Vercel-hosted: Not affected
  • Fixed versions: 15.5.16, 16.2.5
  • Fix: Upgrade handler now destructures finished and statusCode from resolveRoutes and gates the proxy call on finished && parsedUrl.protocol && !statusCode, the same routing-completion check the HTTP request handler already performed.
  • Exploitation: No authentication required; single GET with an absolute-form request-line URI

Timeline

  • May 4, 2026: Fix committed to Next.js canary (`846b7f82`)
  • May 11, 2026: GHSA-c4j6-fc7j-m34r published; CVE-2026-44578 assigned; Next.js 15.5.16 and 16.2.5 released
  • Current: Public proof-of-concept code available

Vulnerability scope and affected deployments

CVE-2026-44578 affects self-hosted Next.js applications using the built-in Node.js server. Vercel-managed deployments and applications running on Vercel’s infrastructure are explicitly not affected. The vulnerability does not impact Next.js applications deployed on other managed platforms such as Netlify, AWS Amplify, or other PaaS providers that do not expose raw WebSocket upgrade capabilities.

Approximately 740,000 publicly reachable Next.js servers are indexed on Shodan globally. The directly-exposed subset (no reverse proxy in front, running on the default `next start` port 3000) numbers around 118,700 hosts. Sampling within that cohort shows roughly 66.7% are running vulnerable versions, yielding an estimate of ~79,000 hosts that are directly exploitable today. The broader affected surface includes any self-hosted Next.js instance running versions 13.4.13 and later (except 15.5.16+ and 16.2.5+) that is reachable from an attacker over the network.

Deployment patterns at risk

Self-hosted Next.js deployments vulnerable to CVE-2026-44578 include:

  • Applications running on dedicated servers or virtual machines with Node.js
  • Docker containers exposing port 80 or port 443 without reverse-proxy protection
  • Kubernetes deployments running Next.js directly on ingress
  • Development and staging environments running unpatched versions
  • Applications deployed on private infrastructure but accessible via load balancers

Cloud-native deployments using serverless functions (AWS Lambda, Google Cloud Functions, Azure Functions) are not vulnerable because serverless platforms do not expose the HTTP upgrade pathway. Managed platforms that reject absolute-form request URIs before they reach the Next.js process are also protected.

Configuration dependency

WebSocket upgrade support is built into Next.js's router and cannot be disabled via configuration. No additional setup is required for the vulnerable code path to be reachable. Any self-hosted Next.js server on an affected version that accepts inbound HTTP from the attacker is exploitable, regardless of which port Next.js is listening on (commonly 3000 by default, but the listener port is irrelevant to exploitability). The target of the SSRF, by contrast, is pinned to port 80 due to a URL-normalization quirk in the bug's code path. See the next section.

Vulnerability mechanism

A server-side request forgery vulnerability occurs when an application server processes requests from untrusted sources and uses those requests to trigger outbound HTTP calls to internal or external resources without proper authorization. SSRF in the context of cloud infrastructure is particularly dangerous because attackers can access cloud metadata services (such as AWS EC2 Instance Metadata Service, GCP metadata endpoints, or Azure Instance Metadata Service) to retrieve credentials, keys, and configuration data.

In CVE-2026-44578, the vulnerability exists in Next.js's HTTP/1.1 WebSocket upgrade handler in packages/next/src/server/lib/router-server.ts. When a client sends an HTTP Upgrade request with Connection: Upgrade and Upgrade: websocket headers, the upgrade handler calls resolveRoutes to determine the request's destination. The vulnerable handler then checks only parsedUrl.protocol before forwarding to proxyRequest, ignoring the finished and statusCode flags that the equivalent HTTP request handler had always honoured. By sending an absolute-form URI in the request line (e.g. GET http://169.254.169.254/path HTTP/1.1, legal per RFC 7230 §5.3.2), an attacker causes parsedUrl.protocol to be set to http: without routing actually approving the proxy operation. The server then opens a connection to the attacker-specified host on port 80.

Attack vector: WebSocket upgrade handler bypass

The attack chain operates as follows:

1. Attacker opens a TCP connection to the public Next.js server

2. Attacker sends an HTTP/1.1 request whose request line uses an absolute-form URI pointing to the internal target, plus the standard WebSocket upgrade headers, e.g.:

   ```

   GET http://169.254.169.254/latest/meta-data/ HTTP/1.1

   Host: <next.js-host>

   Connection: Upgrade

   Upgrade: websocket

   Sec-WebSocket-Version: 13

   Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

   ```

3. Node fires the `upgrade` event because of the upgrade headers

4. Next.js's upgrade handler sees `parsedUrl.protocol = 'http:'` and calls `proxyRequest` without checking whether routing approved the proxy

5. `proxyRequest` opens a connection to the absolute URL's host on port 80 (the explicit port in the URL is stripped by the URL-normalization step) and forwards the request

6. The internal service's response is piped back to the attacker over the same socket

The core issue is an asymmetry between the two handlers in router-server.ts. The HTTP request handler had always gated its proxy call on both finished (routing actually completed) and parsedUrl.protocol (external destination); the upgrade handler gated on parsedUrl.protocol alone. The fix simply destructures finished and statusCode from resolveRoutes in the upgrade handler and adds the missing checks. This is a routing-completion bug, not an authorization or middleware issue. Middleware never ran on either path.

Exploitation conditions

Successful exploitation requires:

  • Public network access to the vulnerable Next.js server
  • Ability to send HTTP requests to any endpoint (no path restriction)
  • Target internal resource reachable from the Next.js server on port 80
  • WebSocket upgrade support enabled (default)
  • Vulnerable version (13.4.13 to 15.5.15, or 16.0.0 to 16.2.4)

The vulnerability does not require:

  • Authentication credentials
  • Cookies or session tokens
  • Knowledge of internal URLs (standard cloud metadata endpoints are well-known)
  • Exploitation tools beyond curl or a web browser

Root cause

The bug lives in the upgradeHandler function in router-server.ts. Before the fix, the relevant section looked like this:

diff

-      const { matchedOutput, parsedUrl } = await resolveRoutes({

-        req,

-        res,

-        isUpgradeReq: true,

-        signal: signalFromNodeResponse(socket),

-      })

+      const { finished, matchedOutput, parsedUrl, statusCode } =

+        await resolveRoutes({

+          req,

+          res,

+          isUpgradeReq: true,

+          signal: signalFromNodeResponse(socket),

+        })

      // TODO: allow upgrade requests to pages/app paths?

      // this was not previously supported

      if (matchedOutput) {

        return socket.end()

      }

-      if (parsedUrl.protocol) {

-        return await proxyRequest(req, socket, parsedUrl, head)

+      if (finished && parsedUrl.protocol) {

+        if (!statusCode) {

+          return await proxyRequest(req, socket, parsedUrl, head)

+        }

+

+        return socket.end()

      }

The vulnerable code destructures only { matchedOutput, parsedUrl } from resolveRoutes and then immediately calls proxyRequest whenever parsedUrl.protocol is truthy. It never checks whether routing actually approved the proxy operation.

How parsedUrl.protocol gets set without routing approval

resolveRoutes starts with:

let parsedUrl = url.parse(req.url || '', true) as NextUrlWithParsedQuery

Node.js's http module preserves the request target verbatim in req.url. HTTP/1.1 allows absolute-form request targets, meaning a client can legally send:

GET http://internal-service:8080/secret HTTP/1.1

Host: public-app.example.com

Connection: Upgrade

Upgrade: websocket

When req.url is http://internal-service:8080/secret, url.parse produces a parsedUrl with protocol: 'http:'. That's enough to satisfy the if (parsedUrl.protocol) check, and proxyRequest is called unconditionally.

The normalizeRepeatedSlashes interaction

resolveRoutes has an early-exit guard for URLs containing // or \:

if (urlNoQuery?.match(/(\\|\/\/)/)) {

  parsedUrl = url.parse(normalizeRepeatedSlashes(req.url!), true)

  return {

    parsedUrl,

    resHeaders,

    finished: true,

    statusCode: 308,

  }

}

The // in http:// causes resolveRoutes to take the normalizeRepeatedSlashes early-exit branch, returning finished: true and statusCode: 308, signalling that routing produced a redirect, not an approved external proxy target. The vulnerable upgrade handler ignores both flags. It checks only parsedUrl.protocol, sees 'http:', and proceeds to call proxyRequest anyway.

Despite the URL-normalization mangling, the hostname the attacker supplied survives end-to-end: proxyRequest and the underlying http-proxy library reconstruct a usable target and open the outbound TCP connection to the host named in the absolute-form URI (169.254.169.254, metadata.google.internal, or wherever the attacker pointed it). The explicit port (:8080, :9876, etc.) does not survive normalization; it is dropped, and Node's http.request falls back to its default of port 80.

Observed attacks and proof-of-concept

Public proof-of-concept code for CVE-2026-44578 was released within days of the advisory. Confirmed exploits demonstrate:

  • Enumeration of internal network services on port 80
  • Exfiltration of internal admin panel configurations
  • Retrieval of API keys and secrets stored in environment or configuration files

Researchers have confirmed that attackers can extract cloud credentials in seconds using only HTTP GET requests to publicly reachable Next.js servers. The leaked credentials often grant broad permissions within the cloud environment, enabling lateral movement and data exfiltration.

Impact on cloud environments

The impact of CVE-2026-44578 is particularly severe in cloud-hosted environments because:

  • Cloud metadata services on port 80 are reachable from inside the instance: AWS IMDSv1 (`169.254.169.254`), GCP metadata (`metadata.google.internal`, though GCP rejects requests carrying `Upgrade: websocket` with 400), Azure IMDS, Oracle OCI (`/opc/v1/...`), and DigitalOcean metadata. AWS IMDSv2 is largely *not* exploitable: it requires a `PUT /latest/api/token` to mint a session token, which this GET-only SSRF cannot perform, and it rejects requests carrying `X-Forwarded-For` (which `http-proxy` adds by default)
  • Credentials retrieved from metadata services grant access to storage buckets, databases, and other cloud resources
  • The attack is conducted over standard HTTP (port 80), which is typically not rate-limited or monitored as intensively as other attack vectors
  • Exploitation leaves minimal forensic traces (requests appear to come from the application server itself)
  • Organizations using cloud environments commonly store secrets in instance metadata, environment variables, or configuration files. A successful SSRF attack can expose:
  • AWS EC2 role credentials (STS tokens scoped to whatever IAM permissions are attached to the instance role)
  • Azure managed identity tokens
  • Database credentials and connection strings
  • API keys for internal and third-party services
  • SSH private keys and deployment credentials

Detection and forensics

Server-side detection

Organizations can identify exploitation attempts through:

  • Next.js process logs containing the string `Failed to proxy http:/` (note the single slash after `http:` — that's the normalisation fingerprint and is a reliable indicator that the vulnerable SSRF path fired)
  • Reverse-proxy or access logs showing request lines that begin with `http://` or `https://` (absolute-form URIs) accompanied by `Upgrade: websocket` — the precise signature of the exploit
  • Unusual outbound connections from the Next.js process to cloud-metadata endpoints (`169.254.169.254:80`, `metadata.google.internal:80`) or to RFC 1918 / link-local addresses on port 80 with no corresponding inbound request to a configured rewrite route

However, these indicators are not consistently logged in all configurations. Many Next.js deployments do not log HTTP upgrade requests at all, since they never complete a normal request/response cycle. The connection is hijacked at the socket level. If you do not currently log upgrade attempts, add packet capture or reverse-proxy access logs for the upgrade pathway.

Network-level detection

Network security tools can detect:

  • HTTP upgrade requests to public Next.js endpoints followed by unusual outbound traffic
  • Requests to cloud metadata endpoints from application servers that should not need metadata
  • High-frequency WebSocket upgrade requests from external sources

Recommended actions

Immediate (within 24 hours)

  • Identify all self-hosted Next.js deployments in your infrastructure
  • Check version of Next.js running on each deployment (check `package.json` or run `npm list next`)
  • Determine if deployment is self-hosted (not Vercel-managed, Netlify, or other PaaS)
  • Upgrade Next.js to version 15.5.16 or 16.2.5 (or latest patched version in your minor)

Short-term (within 48-72 hours)

  • Upgrade Next.js to version 15.5.16 or 16.2.5 (or latest patched version in your minor)
  • If unable to upgrade immediately, implement reverse-proxy-based mitigations (detailed in the Mitigation section below):
  • Place nginx / Caddy / HAProxy in front of Next.js if not already — they reject absolute-form request lines by default
  • Add an explicit reject rule for request URIs beginning with `http://` or `https://`
  • On AWS, enforce IMDSv2 (HttpTokens=required), as this neutralises the most damaging exploitation path even on unpatched instances.
  • Test application functionality after patch to verify no regressions
  • Restart application servers to load patched code

Mitigation for deployments that cannot upgrade immediately

Temporary mitigations for organizations that cannot patch within 24 hours:

Reverse proxy blocking

The precise signature of the exploit is an absolute-form URI in the HTTP request line (e.g. `GET http://...` instead of `GET /...`). Mainstream reverse proxies — nginx, Caddy, HAProxy — already reject or rewrite absolute-form request lines for normal HTTP requests by default. Placing one of these in front of Next.js significantly reduces exposure.

For defence-in-depth, you can explicitly reject request URIs that begin with a scheme:

```

# Nginx: reject absolute-form request URIs

if ($request_uri ~* "^https?://") {

    return 400;

}

```

Do not blanket-block `Upgrade: websocket as that breaks every legitimate WebSocket feature in your application. The vulnerability is specific to the combination of an upgrade header and an absolute-form request line.

WAF rules

If your WAF supports inspecting the HTTP request line, configure it to:

  • Reject inbound requests whose request line begins with `http://` or `https://`. This is the precise exploit signature and does not false-positive on legitimate traffic.
  • Alert on outbound connections from the Next.js process to `169.254.169.254`, `metadata.google.internal`, or any RFC 1918 / link-local address on port 80 that does not correspond to a configured rewrite destination.

Context

CVE-2026-44578 was published alongside several other Next.js and React Server Components advisories in the May 2026 security batch. Organisations running Next.js should review the full Vercel security release for the period to assess exposure beyond CVE-2026-44578; the canonical list lives in the official advisory (linked below) rather than being reproduced here.

Verification and Detection

Organizations using Hadrian’s continuous exposure management platform can:

  • Automatically identify publicly reachable Next.js deployments
  • Scan for vulnerable versions without triggering false positives
  • Detect active exploitation attempts targeting metadata endpoints
  • Validate patch deployment across infrastructure

References and Resources

Official Advisories

  • [Next.js Security Release (May 2026)](https://nextjs.org/blog/security-release-2026-05) - Official Vercel advisory
  • [GitHub Advisory GHSA-c4j6-fc7j-m34r](https://github.com/vercel/next.js/security/advisories/GHSA-c4j6-fc7j-m34r) - Full CVE-2026-44578 details
  • [CVE-2026-44578 NVD Entry](https://nvd.nist.gov/vuln/detail/CVE-2026-44578) - National Vulnerability Database
  • [Next.js 16.2.5 Release Notes](https://github.com/vercel/next.js/releases/tag/v16.2.5) - Patched version details

Technical Analysis

  • [Cloudflare WAF Changelog](https://developers.cloudflare.com/waf/) - Protection rules and detection

Mitigation and Detection

  • [AWS Security Best Practices for Next.js](https://aws.amazon.com/security/) - Securing cloud-native applications
  • [Hadrian EASM Platform](https://hadrian.io/atlas) - Continuous discovery of exposed Next.js instances
  • [Hadrian Autonomous Pentesting](https://hadrian.io/nova) - Automated validation of vulnerability exploitability

{{related-article}}

Next.js WebSocket SSRF: Unauthenticated Access to Internal Resources: CVE-2026-44578

{{quote-1}}

,

{{quote-2}}

,

Articles associés.

Tous les articles

Alertes de vulnérabilité

CVE-2026-41940: A Critical Authentication Bypass in cPanel

CVE-2026-41940: A Critical Authentication Bypass in cPanel

Alertes de vulnérabilité

CVE-2025-53690: Critical vulnerability in Sitecore leads to remote code execution

CVE-2025-53690: Critical vulnerability in Sitecore leads to remote code execution

Related articles.

All resources

Alertes de vulnérabilité

CVE-2026-23918: Apache HTTP Server Double-Free RCE in HTTP/2 Implementation

CVE-2026-23918: Apache HTTP Server Double-Free RCE in HTTP/2 Implementation

Alertes de vulnérabilité

CVE-2026-41940: A Critical Authentication Bypass in cPanel

CVE-2026-41940: A Critical Authentication Bypass in cPanel

Alertes de vulnérabilité

cPanel Critical Authentication Bypass Actively Exploited - CVE-2026-41940

cPanel Critical Authentication Bypass Actively Exploited - CVE-2026-41940

get a 15 min demo

Start your journey today

Hadrian’s end-to-end offensive security platform sets up in minutes, operates autonomously, and provides easy-to-action insights.

What you will learn

  • Monitor assets and config changes

  • Understand asset context

  • Identify risks, reduce false positives

  • Prioritize high-impact risks

  • Streamline remediation

The Hadrian platform displayed on a tablet.
No items found.