Most "secure your Next.js app" posts read like a tour of next.config.js.
This is the checklist I actually run against an App Router app before signing
off on it.
A01 — Broken access control
- Every Server Action and Route Handler explicitly checks the session — never trust the URL or the client component that called it.
- Authorization is enforced server-side, never via
useEffectguards. - Middleware (or Routing Middleware on Vercel) handles cross-cutting auth decisions like "private routes require a session."
A02 — Cryptographic failures
- Secrets live in
process.env, not in client components. If a secret leaks into a client bundle,vercel envis misconfigured. - TLS is enforced (Vercel does this; on custom hosts, add HSTS).
- Hashing uses libraries (
bcrypt,argon2) — never custom rolls.
A03 — Injection
- All database access is via parameterized queries or an ORM that does it for you. Drizzle / Prisma both default safely; raw SQL is where injection lives.
- Server Actions validate inputs with Zod (or similar) before they touch the database.
- HTML rendered from user content is escaped by React's default behavior —
audit any
dangerouslySetInnerHTMLcarefully.
A04 — Insecure design
- Threat-model before you scaffold. What's the worst thing a user can ask of this endpoint? Build assuming they will.
A05 — Misconfiguration
next.config.tsis reviewed: nounsafe-evalin CSP, headers set, no source maps shipped to prod for sensitive code.- Static error pages don't leak stack traces.
A06 — Vulnerable components
- Dependencies pinned.
npm auditruns in CI. - React, Next, and the bundler are on supported majors.
A07 — Auth failures
- Sessions are HTTP-only, Secure, SameSite cookies — never local storage.
- Rate-limit on login and password-reset routes.
- Use a marketplace auth provider (Clerk, Auth0) unless you have a strong reason not to.
A08 — Software & data integrity
- SRI on third-party scripts. Lockfile committed. Build artifacts not modifiable post-deploy (Vercel handles this).
A09 — Logging & monitoring
- Sentry or equivalent capturing server errors. Login failures logged separately from app errors so they don't drown.
A10 — SSRF
See the SSRF post — short version: never let user input become an outbound fetch target without DNS-resolved allow-listing.
This isn't comprehensive. It's the order I work in.