← All buildersNext.js

Is my Next.js app secure? Framework-level checks before you ship

Next.js is the framework underneath most AI-generated frontends, and by default it ships with no security headers, browser source maps enabled in production, and no built-in enforcement that a Server Action or API route actually checks who's calling it. All of that is left to explicit configuration the generated code doesn't always include.

Why this happens in Next.js apps

Next.js gives you a huge amount out of the box (routing, server rendering, API routes, Server Actions), but "out of the box" for security specifically means very little is on by default. The framework assumes you'll add headers, auth checks, and build config deliberately, which is easy to skip when a prompt-driven workflow is optimizing for a working feature, not a hardened one.

Server Actions in particular can look like they're protected because they're "server-side," but Next.js doesn't know or enforce which actions should require a signed-in user; a Server Action is reachable by anyone who can construct the right request unless the action itself checks the session.

Common issues in Next.js apps

What actually shows up in Next.js apps regardless of which AI tool generated them:

  • Missing security headers: a default Next.js app sets no Content-Security-Policy, HSTS, or X-Frame-Options; these have to be added explicitly via headers() in next.config.js or middleware.
  • Secrets in NEXT_PUBLIC_ environment variables: any variable prefixed NEXT_PUBLIC_ is inlined into the client bundle at build time; a key that only needed to be read server-side but got that prefix by habit ships to every visitor.
  • Source maps served in production: production builds emit browser source maps unless productionBrowserSourceMaps is explicitly set to false, handing out original, unminified source to anyone who requests the .map file.
  • Server Actions and API routes without an auth check: a Server Action or route handler runs whatever code it contains for any request that reaches it; Next.js doesn't infer "this should be logged-in only" from your UI, that check has to be written explicitly inside the action itself.

How to fix it

These are framework-config-level fixes, not a rewrite:

  • Add a headers() function in next.config.js covering CSP, HSTS, and X-Frame-Options for all routes.
  • Audit every NEXT_PUBLIC_-prefixed variable and confirm each one is genuinely safe to expose to the browser.
  • Set productionBrowserSourceMaps: false unless you have a specific reason to ship maps publicly.
  • Add an explicit session check at the top of every Server Action and API route handler that should require authentication. Never assume the calling UI is the only way the route gets reached.

Frequently asked

Does the App Router handle security differently from the Pages Router?

The mechanics differ (Server Actions and Route Handlers vs. API routes), but the underlying gap is the same in both: nothing in the framework infers or enforces an auth requirement on your behalf. Every protected action or route needs an explicit check written into it.

If a Server Action is only called from a button in my UI, is it actually protected?

No. A Server Action compiles down to a callable endpoint at a predictable URL. Anyone who inspects the network request your button makes can call that same action directly, bypassing your UI and any client-side checks entirely.

//Get started//

Ready to make it unbreachable?

Point us at your app and get a full breakdown of what's exposed in about two minutes. Every finding comes with the fix.

Shipping with an AI builder? See how verification works