For: anyone running a Next.js app (App Router assumed). No attack steps here — this is a working reference for hardening: a priority-ordered checklist, per-area guidance, and self-verification. For the cross-framework picture, see the security-by-framework hub.
Priority-ordered hardening checklist
Do this table top-down. P0 is a prerequisite, P1 is the most frequent source of incidents, P2 is ongoing maintenance.
P0 ── Prerequisite (do first)
Keep secrets out of the browser / dependency CVE monitoring + fast patching / firm production config
P1 ── Top source of incidents
Server Actions/Route Handlers authorization + input validation / SSRF on server fetches
P2 ── Ongoing maintenance
Headers/CSP / auth, session, cookies / rate limiting
| Priority | Control | Specifics (Next.js) |
|---|---|---|
| P0 | Secrets out of the browser | NEXT_PUBLIC_ only for browser-safe values; secrets only in Server Component/Action/Route Handler |
| P0 | Dependency CVEs | Monitor with npm audit/osv-scanner; judge by running version, patch fast. Keep up with core RCE |
| P0 | Production config | Run a production build; don't leak internals (stack/env) on errors |
| P1 | Action authorization | Authentication + owner-scoped authorization in every Server Action/Route Handler |
| P1 | Input validation | Schema-validate inputs (type/range/allowed). Don't trust the client |
| P1 | SSRF protection | Restrict server-side URL fetches to an allowlist + block internal IPs/metadata. Limit image remote patterns |
| P2 | Headers/CSP | Security headers + HSTS in next.config. Consider a nonce-based CSP on App Router |
| P2 | Auth/cookies | Secure/HttpOnly/SameSite session cookies. Don't leave authorization to middleware alone |
| P2 | Rate limiting | Limits on auth, Server Actions, and Route Handlers |
1. The server/client boundary and env vars (P0)
Next.js's biggest source of incidents is secrets that were meant to be server-only ending up in the client.
- Only prefix browser-safe values with
NEXT_PUBLIC_. Never on API keys or connection info (NEXT_PUBLIC_values are embedded in the client bundle at build time and visible to visitors). - Read secrets only inside Server Components / Server Actions / Route Handlers, and keep them out of
propsand responses (serialized values). - Keep server-only modules from being imported by the client (accidental inclusion can bundle secrets). See .env files and secrets.
2. Dependency CVEs and the core (P0)
- Machine-monitor dependency (npm) CVEs with
npm auditor osv-scanner, judge by the running version, and patch fast (decide on what's actually installed, not the package.json declaration). - Next.js core has had serious RCEs, so keep up quickly when one is published. For the operating discipline see not falling behind on CVEs; for practice, the vulnerability-response playbook.
- Keep Node/Next on supported versions and don't leave EOL versions in place.
3. Server Actions / Route Handlers (authorization + validation, P1)
These are server-side functions that anyone can call. Being callable doesn't mean it's allowed.
Common (dangerous)
- actions treated as "logged in = allowed"
- relying on middleware auth alone, no ownership check
- input passed to DB or external calls unvalidated
- trusting client-supplied values (IDs, flags) as-is
Correct
- authentication plus owner/permission-scoped authorization in every action/handler
- don't leave it to middleware (authorize close to the data)
- schema-validate input (type/range/allowed)
- re-verify on the server so ID swaps don't work
See what IDOR is. Do an ownership check on every read/update/delete path.
4. SSRF and server-side fetches (P1)
Server-side fetching of user-supplied URLs (image proxies, webhooks, metadata fetches) is where SSRF typically happens.
- Restrict targets to an allowlist, and at connection time block reaching private IPs and cloud metadata (169.254.169.254).
- Keep image-optimization remote patterns to a minimum (don't allow fetching arbitrary hosts).
- See what SSRF is. This site routes outbound fetches through an SSRF-safe gateway.
5. Injection and output
- XSS: React escapes output by default. Don't pass user input to
dangerouslySetInnerHTML(only after sanitizing if truly needed). See what XSS is. - SQL/injection: bind with an ORM/placeholders; never build queries by string concatenation (→ what SQL injection is).
- Don't pass external input to dangerous evaluation like
eval.
6. Security headers and CSP (P2)
- Set security headers (X-Content-Type-Options, etc.) and HSTS in
next.config. Check your own site with the security headers checker. - On App Router, consider a nonce-based CSP (avoid blanket-allowing inline scripts). Note that coexisting with analytics/ad tags takes design.
7. Auth, session, cookies (P2)
- Set Secure / HttpOnly / SameSite on session cookies.
- Don't delegate authorization to middleware auth alone. Middleware is a supplement; verify the actual decision in the action/handler/data layer (some paths can bypass middleware).
- Regenerate and expire sessions appropriately on login.
8. Rate limiting (P2)
- Apply attempt/throughput limits to auth, Server Actions, and Route Handlers to curb brute force, abuse, and DoS.
Verify: is your Next.js actually hardened?
Building it isn't the end — it's done only once you've checked. These are defensive self-checks against your own site/environment.
No secrets leaked to the client
NEXT_PUBLIC_.Production doesn't leak internals on errors
Action authorization holds
Headers, dependencies, SSRF
npm audit/osv is clean, and that outbound fetches can't reach internal IPs.This site's view: focus on the server/client boundary and dependencies
This site runs on Next.js, and the focus isn't special config but the server/client boundary and keeping dependencies up to date. Secrets stay on the server, publicly callable functions (Server Actions/Route Handlers) always carry authorization and input validation, and dependencies get a CVE audit before every deploy. This site was started after an incident in which an unpatched CVE was exploited automatically, so machine-monitoring dependencies is a top-priority habit. Outbound URL fetches go through an SSRF-safe gateway so they can't reach internal IPs or metadata.
Read next
- Hub: security by framework · Laravel security
- Dependencies: not falling behind on CVEs · the vulnerability-response playbook
- Glossary: what IDOR is · what SSRF is · .env files and secrets · XSS
- Tools: security headers checker
Sources and scope
These primary references support the settings, scope or remediation discussed above; links were checked on October 23, 2026. Consult their version and configuration conditions. Checklist priorities and lessons are this site's guidance, not a full-article revalidation or a safety guarantee.