Skip to content
BuildThenTestedSee packages

Next.js security: defaults, what breaks, what to check

Next.js is a React framework with server components, server actions, route handlers and a proxy layer that runs before routes. Below: what it configures by default according to its own documentation (verified 2026-09-21), the 15 patterns most associated with it, the security features the vendor offers and where they stop, and a checklist you can run without buying anything.

Docs verified at Next.js version 16.3.5 as shown on the pages; the middleware file convention is deprecated in favour of proxy.

Next.js runs React on the server and the client. Its docs describe three things that matter for security testing. Only NEXT_PUBLIC_ variables reach the browser. An exported Server Action is reachable by a direct POST regardless of the page's UI. A page-level auth check does not extend to the Server Actions defined in it.

So the tests for a Next.js app are about server boundaries. Which variables were prefixed for the browser. Whether every Server Action and route handler checks the caller itself. Whether the proxy (formerly middleware) is doing work that should live in a data access layer.

Next.js defaults that matter for testing

Each row is taken from the vendor's documentation on the date shown. Defaults change; the date is the claim.

Defaults of Next.js as documented by the vendor
AreaDefaultSource
NEXT_PUBLIC_ prefix exposureBy default environment variables are only available on the server; variables prefixed NEXT_PUBLIC_ are inlined into the browser bundle at build time and frozen at that value.docs · verified 2026-09-21
.env filesThe default create-next-app template adds all .env files to .gitignore; Next.js loads .env, .env.local and per-environment files from the project root.docs · verified 2026-09-21
Server actionsAn exported Server Action is reachable via a direct POST request, not just the UI. Next.js adds encrypted non-deterministic action IDs, dead code elimination and an Origin to Host check. The docs say to verify authentication and authorization inside each action.docs · verified 2026-09-21
Middleware / proxy caveatsmiddleware is deprecated and renamed proxy; it runs on every route unless matched, defaults to the Node.js runtime, and Server Function calls on excluded paths skip it. The docs say to verify auth inside each Server Function rather than relying on Proxy alone.docs · verified 2026-09-21
Page-level checksA page-level authentication check does not extend to the Server Actions defined within it; returning null in a layout does not stop nested segments or actions from being reached.docs · verified 2026-09-21

Documentation home: nextjs.org/docs

What breaks in Next.js projects

36 patterns in the catalogue name Next.js; the most severe are listed here across secrets and keys, data access, login and permissions, payments, ai features. Attribution is descriptive: the default stack makes the pattern reachable, or a public incident names it.

Public incidents

Lovable reported that from 3 February to 20 April 2026 a backend regression let any logged-in Lovable user read the chat history and source code of public projects; a fix shipped within two hours.

  • 2026-02-03 to 2026-04-20 Exposure window
  • 2026-02-22 First HackerOne report
  • about 2 hours Time from public report to fix

Apr 2026 · Lovable · all sources

One education app built on Lovable had 16 vulnerabilities, 6 critical; a database function denied callers whose role was 'authenticated', so anonymous callers passed and 18,697 user records were readable without login.

  • 16 Vulnerabilities found
  • 6 Critical
  • 18,697 User records exposed
  • 14,928 Unique email addresses
  • 870 Enterprise users with full PII

Feb 2026 · Taimur Khan · all sources

On the Base44 app builder, undocumented registration and one-time-password endpoints accepted a non-secret app_id, so anyone could create a verified account on a private app; Wix fixed it within 24 hours.

  • 2025-07-09 Reported to Wix
  • 2025-07-10 Fix verified
  • under 24 hours Time to fix
  • 2025-07-29 Public disclosure

Jul 2025 · Wiz Research · all sources

Two days after announcing a SaaS built with Cursor and no hand-written code, its founder reported subscription bypasses, maxed-out API keys and unwanted database writes; he shut the app down three days later.

  • 2025-03-15 Launch announcement
  • 2025-03-17 Report of subscription bypass and API key abuse
  • 2025-03-20 Shutdown announcement

Mar 2025 · Leo (Enrichlead founder) · all sources

Each entry links to its primary source in the evidence list. What to do about it is the self-check below.

Next.js's own security features, and where they stop

Stated from the vendor's documentation. The limits are the vendor's scope statements, not judgements.

  • server-only package

    Marking a module with import 'server-only' causes a build error if it is imported into the client environment.

    Where it stops: Protects module boundaries; it does not filter the data a server component passes to client components.

    vendor docs · verified 2026-09-21

  • React Taint APIs

    experimental_taintObjectReference and experimental_taintUniqueValue, enabled via experimental.taint, prevent tainted objects or values from being passed to the client.

    Where it stops: Experimental and described as an additional layer; the docs say to still filter and sanitize data in a Data Access Layer.

    vendor docs · verified 2026-09-21

  • Server Action protections

    Encrypted action IDs regenerated per build, removal of unused actions from the client bundle, POST-only invocation and an Origin to Host header comparison against CSRF.

    Where it stops: The docs state these reduce risk where an auth layer is missing but that actions must still be treated as public POST endpoints and check authentication and authorization, including resource ownership.

    vendor docs · verified 2026-09-21

  • Data Access Layer guidance

    The authentication guide recommends a server-only Data Access Layer with verifySession(), DTOs that return only needed fields, and treating Route Handlers like public API endpoints.

    Where it stops: A pattern to implement, not a built-in enforcement; Proxy is described as optimistic checks only, not the sole line of defence.

    vendor docs · verified 2026-09-21

Check it yourself, in this order

The critical patterns first. Each uses the dashboard and your browser.

NEXT_PUBLIC_ prefix on a secret

  1. In your hosting dashboard (Vercel: Project, Settings, Environment Variables) or your .env files, list every variable whose name starts with NEXT_PUBLIC_.
  2. For each one, ask whether the provider calls that value secret, private, server or admin. Stripe secret keys, model provider keys, database passwords and Supabase service_role keys all fall in that group.
  3. Open the live site in Chrome, right-click, choose Inspect, open the Sources tab and press Ctrl+Shift+F. Search for the first few characters of each suspect value.
  4. A bad result is a NEXT_PUBLIC_ variable holding a server-only key, or a search hit for that key's value in a loaded script.

Secrets committed to the code repository

  1. Open your project on GitHub (or the code view in your builder) and look at the file list for .env, .env.local, .env.production, serviceAccountKey.json or firebase-adminsdk files.
  2. Use the repository search box and search for sk_live, sk-, service_role, BEGIN PRIVATE KEY and password=.
  3. If you have the code on your computer, run one command in the project folder: git log --all -p -S sk_live -- . | head. Any output means a live key has been committed at some point.
  4. On GitHub, open Settings, then Code security, and check whether Secret scanning shows alerts.
  5. A bad result is any env or key file in the file list, any search hit that shows a real key, or an open secret scanning alert.

Service-role key shipped in the browser bundle

  1. Open your live app in Chrome, right-click anywhere and choose Inspect, then open the Sources tab.
  2. Press Ctrl+Shift+F (Cmd+Option+F on a Mac) to search every loaded file. Search for service_role and then for sb_secret_.
  3. Open the Network tab, reload the page, click any request whose address contains supabase.co, and read the apikey header under Request Headers.
  4. In the Supabase dashboard, open Project Settings, then API Keys, and compare that header value with your keys.
  5. A bad result is any search hit, or a header value that matches the service_role or secret key rather than the anon or publishable key.

Next.js pre-launch checklist

36 checks, in the order we run them. Usable without buying anything.

Self-check tool

Answer questions about your setup and get the patterns that apply, ordered by severity. Runs in your browser; nothing is sent.

Run the self-check

Packages for Next.js projects

Pre-launch check

Start here

For founders about to let real users in.

$490

Report in 48 hours
  • Keys and secrets in the browser or repo
  • Who can read and change whose data
  • Login, roles and admin routes
  • Errors, retries and rate limits
  • Debug mode, headers, deploy path

What you receive

Security sweep

For anyone who wants the three riskiest areas checked fast.

$290

Report in 24 hours
  • API keys and secrets in the bundle
  • Row-level rules on every table
  • Cross-user data reads
  • Admin and hidden routes
  • Client-only permission checks

What you receive

All packages and prices. Every report includes a re-check after your fixes.

Questions about Next.js

next js server action security

Each Server Action is an endpoint. Next.js docs recommend verifying the user inside the action or in a data access layer it calls, not only on the page. We call every action directly with a second user's session and report which ones act without checking.

next_public env var secret exposed

Anything prefixed NEXT_PUBLIC_ is inlined into the JavaScript bundle at build time. Search your deployed bundle for the value; if a secret is there, rotate it, remove the prefix and read it on the server only.

next js security checklist

Server-only secrets, a permission check in every Server Action and route handler, the server-only package or Taint APIs on sensitive data, security headers in next.config, and dependency updates. The Next.js patterns on this page map to each item.