Back to guides

Next.js Security Checklist

By Davy Rogers

Use this checklist before shipping a Next.js app to production. Each item is a concrete action, not a vague principle.

Headers

  • Content-Security-Policy is set with script-src restricted (no unsafe-inline without nonces)
  • X-Content-Type-Options: nosniff is set
  • X-Frame-Options: DENY is set (or use CSP frame-ancestors 'none')
  • Strict-Transport-Security is set with a long max-age and includeSubDomains
  • Referrer-Policy is set to strict-origin-when-cross-origin or stricter
  • Permissions-Policy disables unused browser features (camera, microphone, geolocation)
  • X-Powered-By header is removed (poweredByHeader: false in next.config.ts)

Reference: Next.js - Headers

Authentication and Sessions

  • Sessions use HttpOnly, Secure, SameSite=Lax cookies
  • Session tokens are validated server-side on every request
  • Session expiry and rotation are configured
  • Server Actions check authentication before executing
  • Middleware protects authenticated routes

Reference: Next.js - Middleware

Server Components and Data

  • server-only package is installed and used on sensitive modules
  • No secrets or internal data are passed as props to Client Components
  • Database queries run only in Server Components, Server Actions, or Route Handlers
  • Error boundaries do not expose stack traces or internal details

Reference: Next.js - Server Components

Server Actions

  • Every Server Action validates input with a schema library (Zod, Yup, etc.)
  • Every Server Action checks authentication and authorization
  • Server Actions do not accept arbitrary object shapes from the client
  • CSRF protection is in place (validate Origin/Host for Server Actions or use framework/library CSRF protections)

Reference: Next.js - Server Actions Security

API Routes / Route Handlers

  • HTTP methods are validated explicitly
  • Content-Type is validated on POST/PUT/PATCH
  • Rate limiting is applied to sensitive endpoints
  • Error responses do not leak internal information
  • CORS is configured explicitly if needed (not * in production)

Environment Variables

  • No secrets in NEXT_PUBLIC_ variables
  • All required environment variables are validated at build or startup
  • .env.local is in .gitignore

Reference: Next.js - Environment Variables

SSRF

  • User-supplied URLs are validated against an allowlist before server-side fetch
  • Private IP ranges are blocked (10.x, 172.16-31.x, 192.168.x, 169.254.169.254)
  • Redirects from server-side fetch are restricted or disabled

Dependencies

  • npm audit runs in CI and fails on critical/high
  • Lockfile is committed and reviewed
  • Dependabot or Renovate is configured for automated updates
  • Unused dependencies are removed

Reference: GitHub - Dependabot

Deployment

  • output: "standalone" is used for minimal container images
  • Telemetry is disabled: NEXT_TELEMETRY_DISABLED=1
  • Source maps are not exposed publicly (or are uploaded to an error tracker privately)
  • Build output does not include .env files
  • Health check endpoints do not expose version or config details

Reference: Next.js - Deploying

File Uploads

  • File type is validated server-side by content (magic bytes), not just extension
  • File size limits are enforced
  • Uploaded files are stored outside the public directory
  • Filenames are regenerated (never use the user-supplied filename for storage)

Logging and Monitoring

  • Authentication events (login, logout, failure) are logged
  • Server Action failures are logged
  • Logs do not contain passwords, tokens, or PII
  • Error tracking (Sentry, Datadog, etc.) is configured for production

Related Guides

Published 04 Mar 2026

Frequently asked questions

Whats the most missed item on a Next.js launch checklist?
Removing or password-protecting Vercel preview deployments, and confirming no NEXT_PUBLIC_ variable contains a secret. Both leak in ways teams do not always notice until production.
Do I still need security headers if Vercel sets some by default?
Yes. Vercel sets a sensible baseline, but CSP, HSTS, Permissions-Policy, and Referrer-Policy benefit from app-specific tuning in next.config.js or middleware.
Should I disable the X-Powered-By header?
Yes, set poweredByHeader: false in next.config.js. It is low-impact information disclosure but removing it is free.
What about middleware running on the edge?
Treat it as your authentication and CSRF gate. Edge middleware sees every request and is the right place for auth checks, rate-limit decisions, and bot blocking.

Related

Want a professional to look at it?Get an AppSec Health Check.