Troja
All posts
VercelUpdated Jul 18, 2026·14 min read

Vercel Deployment Security: The Production Checklist for Next.js

Vercel makes deploying trivial — and makes a few security footguns trivial too. Here's the production checklist: env scoping, headers, preview protection, and the bundle leak everyone hits.

By The Troja Team
Vercel Deployment Security: The Production Checklist for Next.js — Troja security, SEO and AI-visibility field guide

Easy to deploy, easy to leak

Vercel's developer experience is excellent, which means the security mistakes are also easy to make at speed. This checklist covers the Vercel-and-Next.js-specific ones.

1. The NEXT_PUBLIC_ bundle leak

Any env var prefixed NEXT_PUBLIC_ is inlined into the client bundle and shipped to every visitor. Developers routinely prefix a secret to "fix" an undefined variable and silently publish it.

# Only PUBLIC values should appear here:
grep -r "NEXT_PUBLIC_" .env*

Rule: NEXT_PUBLIC_* is for non-secret config only (analytics IDs, public anon keys). A Stripe secret key, a service-role key, or a database URL must never carry that prefix. If one did, rotate it — it's already public.

2. Environment scoping

Vercel has three environments: Production, Preview, Development. Don't reuse production secrets in preview — preview URLs are easier to discover and share. Scope secrets per environment in the dashboard, and use separate API keys/databases for preview where you can.

3. Protect preview deployments

Every push spins up a public preview URL. If your previews touch real data or expose unfinished admin tooling, enable Deployment Protection (Vercel Authentication or password) so previews aren't crawlable by anyone with the URL.

4. Security headers via config

Set headers once in next.config.js so every route is covered:

// next.config.js
const securityHeaders = [
  { key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" },
  { key: "X-Content-Type-Options", value: "nosniff" },
  { key: "X-Frame-Options", value: "DENY" },
  { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
  { key: "Content-Security-Policy", value: "default-src 'self'" },
];

module.exports = {
  async headers() {
    return [{ source: "/:path*", headers: securityHeaders }];
  },
};

Confirm they actually ship:

curl -sI https://yourapp.vercel.app | grep -i "strict-transport\|content-security"

5. Lock down Route Handlers and Server Actions

  • Every app/api/*/route.ts is public by default — add auth checks inside.
  • Server Actions in modern Next.js validate the Origin against allowedOrigins, but you still must authorize the action (is this user allowed to do this?).
  • Don't return internal error details to the client.

6. Don't trust middleware as your only auth gate

Next.js middleware runs on the edge and is fine for redirects, but it has historically had bypass edge cases and doesn't see everything. Enforce authorization at the data layer too (in the route handler / Server Component that reads data), not only in middleware.

7. Cron and webhook endpoints need secrets

Vercel Cron and external webhooks hit public URLs. Require a shared secret:

export async function GET(req: Request) {
  if (req.headers.get("authorization") !== `Bearer ${process.env.CRON_SECRET}`) {
    return new Response("Unauthorized", { status: 401 });
  }
  // ... do the job
}

For Stripe and similar, verify the signature, not just a bearer token.

8. Source maps and verbose builds

Avoid shipping source maps that expose your server logic to the browser in production, and make sure your error pages don't print stack traces.

9. Custom domains and HSTS preload

Once you're on a stable custom domain over HTTPS, consider submitting it to the HSTS preload list so browsers force HTTPS from the first visit.

10. Least-privilege integrations

Vercel integrations (databases, analytics) often request broad scopes. Grant the minimum, and review which integrations have access to your project periodically.

Pre-deploy checklist

  • No secrets behind NEXT_PUBLIC_
  • Secrets scoped per environment
  • Preview deployments protected
  • Security headers in next.config.js and verified live
  • Route handlers/actions enforce auth + authorization
  • Auth enforced at the data layer, not just middleware
  • Cron/webhook endpoints require a secret or signature
  • No production source maps / leaked stack traces

Treat preview as a separate security environment

A Vercel preview is not merely a smaller production URL. It can contain branch code, test integrations, comments, source-map clues and environment variables selected for the Preview environment. Use separate data and third-party credentials where possible, restrict access with Deployment Protection, and review who can create deployments from forks. Vercel documents Git fork protection specifically to reduce exposure of environment variables and OIDC tokens; disabling it should be an explicit risk decision.

Environment variables are encrypted at rest but visible to project members with access, and changes apply only to new deployments. After rotating a secret, redeploy every affected environment and invalidate the old credential at the provider. A successful dashboard edit does not modify an already-built deployment.

Prefer short-lived identity where integrations support it

For backend-to-backend access, Vercel documents OIDC federation so a deployment can present short-lived identity instead of storing a long-lived cloud credential. In May 2026 Vercel also introduced Trusted Sources for protected deployments, using OIDC tokens for authorized callers. Where that fits your provider, validate audience, subject and environment claims and keep an explicit fallback/revocation procedure.

Automation that must enter a protected deployment should use the documented protection mechanism, ideally a header-based bypass or supported OIDC path, rather than making the entire preview public. Store bypass material as a secret, scope the caller and rotate it when a CI integration is removed.

Verify the deployment, not just the repository

Create a release evidence sheet for production and preview separately: final URL and redirects, protection response, cache headers, CSP/HSTS and other security headers, exposed JavaScript strings, public source maps, runtime error behavior, cron/webhook authentication and the identity of connected integrations. Run the checks after the CDN because platform configuration can differ from local Next.js behavior.

Keep authorization in Route Handlers, Server Actions and the data layer even when a deployment is protected. Deployment Protection controls who can reach an environment; it does not decide whether an authenticated application user can mutate a particular record. The Next.js security practices cover that application boundary, while the Next.js + Supabase checklist adds database authorization.

Scan it with Troja

Troja checks your deployed Vercel app for the leaked NEXT_PUBLIC_ secret, missing headers, unprotected API routes, and exposed previews — then hands you a fix prompt for each. Point it at your production URL before your users (or attackers) find the gaps.

Frequently asked questions

Should Vercel preview deployments use production secrets?

Prefer separate preview credentials and data. Scope variables by environment, protect previews and assume preview URLs may be shared more widely than production. If a production secret must be used, document and minimize its permissions.

Does rotating a Vercel environment variable update existing deployments?

No. Vercel documents that environment-variable changes apply to new deployments. Revoke the old provider credential and redeploy every affected environment.

What does Vercel Git fork protection protect?

Vercel says it requires authorization before deploying pull requests from forks, helping prevent untrusted fork code from receiving project environment data such as variables and OIDC tokens.

Does Deployment Protection replace app authorization?

No. It gates access to a deployment. Route handlers, Server Actions and database operations still need identity, authorization and input validation for each protected action.

Sources and verification notes

Product capabilities are vendor-attributed and source-dated. Technical guidance uses primary documentation or vendor-neutral standards.

  1. Vercel environment variablesPrimary source for environment scoping, access and redeployment behavior.
  2. Vercel security settingsPrimary source for Git fork protection and OIDC-backed backend access.
  3. Vercel Deployment Protection bypass methodsPrimary source for supported automation and share workflows on protected deployments.
  4. Next.js data security guidePrimary framework source for keeping authorization at the application and data-access boundary.

Run the scan this post is about.

Free, no signup. See what's hiding inside your walls in ~30 seconds.

Free scan · no signup · results in ~30 seconds
Vercel Deployment Security: The Production Checklist for Next.js — Troja