// TECHNOLOGIES / VERCEL & NEXT.JS

Vercel

Next.js, proven from the outside.

The exploitable surface of a Next.js app lives in the deployed artifacts — a sk_live_ key compiled into a bundle, a served .js.map that rebuilds your source, a middleware auth gate an attacker can walk straight through. NewScan scans from the attacker's seat and reproduces every signal before recording it — and it never flags your public NEXT_PUBLIC_ publishable keys, which are meant to ship.

Hosted on Vercel ≠ safe everywhere

// where the CVEs actually bite

Most headline Next.js CVEs — the middleware bypass, the image-optimizer SSRF — are patched at Vercel's edge, so a scan of a *.vercel.app app correctly shows negatives for them. That is the point: a clean result there is real, not a miss. The risk moves to self-hosted next start deployments — and to the classes that ship in the bundle regardless of host. NewScan checks both, and tells you which host it's looking at.

// SHIPS REGARDLESS OF HOST

A real secret compiled into the client bundle, and exposed source maps that rebuild your original TypeScript — both readable by anyone, whether you deploy to Vercel or self-host.

// SELF-HOSTED RISK (VERCEL PATCHES IT)

CVE-2025-29927 middleware bypass and the /_next/image SSRF — NewScan proves them by behaviour on a self-hosted target and expects the negative on Vercel.

A real secret in the client bundle

// tool: scan_vercel  critical

NEXT_PUBLIC_ variables are inlined into the JavaScript at build time and readable in DevTools — that is intentional and correct for publishable config. The finding is when a real secret — a sk_live_, a service-role JWT, a database URL — was prefixed NEXT_PUBLIC_ or otherwise bundled. NewScan fetches the deployed /_next/static chunks and runs its prefix-anchored secret signatures.

// WHY THIS IS FALSE-POSITIVE-FREE

A finding records only on an unambiguous secret-class match. Publishable and anon values are meant to be public and stay silent — a Stripe pk_live_, a Supabase anon key, a Firebase apiKey, a Clerk publishable key. Same discriminator NewScan uses everywhere: the value's own prefix decides.

GET /_next/static/chunks/[hash].js NEXT_PUBLIC_STRIPE_SECRET_KEY = "sk_live_…" # critical: rotate + move server-side NEXT_PUBLIC_STRIPE_PUBLISHABLE = "pk_live_…" # public by design — NOT a finding

Exposed source maps

// read-only  medium

A reachable .js.map rebuilds your original TypeScript/JSX — names, comments, internal API-route structure, server-adjacent logic. Production Next.js disables browser source maps by default, so a served map is an explicit deviation, not the norm.

// EXPOSURE PROBE

GET /_next/static/chunks/main.js -> //# sourceMappingURL=main.js.map GET main.js.map -> 200 {"sourcesContent":["…original source…"]}

// FP GUARD

Records only a 200 map that parses with a non-empty sourcesContent. A 404, an HTML shell, an inline data: map, or an empty map is not a finding.

Middleware bypass & image-optimizer SSRF

// self-hosted · behaviour-proven

Two high-impact classes on vulnerable self-hosted deployments — each proven by behaviour, never by a version guess (Next.js leaks no external version).

// CVE-2025-29927 MIDDLEWARE BYPASS  critical

GET /admin -> 401 Unauthorized GET /admin x-middleware-subrequest: middleware -> 200 + protected content

A pure read differential: the protected route flips to 200 under the spoofed internal header. Recorded only on the flip; a Vercel-hosted app won't reproduce it — the correct negative.

// /_next/image SSRF  high · out-of-band

GET /_next/image?url=https://<canary>&w=64&q=75 -> collaborator records the server-side fetch

An over-broad images.remotePatterns lets the optimizer fetch arbitrary hosts (internal services, cloud metadata). Confirmed only by a real out-of-band callback — never by timing.

What NewScan records

// class · method · severity
Finding How NewScan finds it Severity
Secret in client bundle A real secret-class key (sk_live_, AWS, DB URL) in a /_next/static chunk — not a publishable key. critical
Middleware auth bypass A protected route flips 401/403 → 200 under a spoofed x-middleware-subrequest (CVE-2025-29927). critical
Image optimizer SSRF /_next/image?url= fetches a canary server-side, confirmed out-of-band. high
Source maps exposed A served .js.map parses with a non-empty sourcesContent. medium
x-matched-path disclosure Responses leak the internal route pattern on the x-matched-path header. low

Recent Next.js security issues

// why these checks matter

External links; referenced for context. CVE severities and details are the publishers'.

How it's recorded

// audit-ready evidence

CATEGORY

The bundled secret maps to OWASP API3; the middleware bypass to API1; the image SSRF to API7; source maps to API8.

SEVERITY

One calibrated severity per finding that translates into each framework's risk rating and remediation SLA — no inflated numbers.

EVIDENCE

Every finding stores the exact request and the differential that proved it — the 401→200 flip, the served map, the secret pattern, or the out-of-band callback.

Point it at your Next.js app.

NewScan is free and self-hosted — bring your own key. The source-map, bundled-secret, and middleware-bypass checks run in the deterministic floor with no model or provider key at all; the /_next/image SSRF is confirmed out-of-band when a collaborator is configured. Whether you're on Vercel or self-hosting, it tells you which — and never flags your public NEXT_PUBLIC_ keys.