VercelApril 22, 20269 min read

Vercel Security Issues Every Developer Should Check in 2026

Given the recent Vercel security incident, here are the seven Vercel-specific security issues we find in customer apps every week, and why fixing them matters more than choosing a different host.

By Jacob

Founder, Vibe App Scanner

Vercel disclosed a platform security incident in April 2026. The details are in their official bulletin and we'll let Vercel speak to what happened on their end.

When incidents like this make the rounds, the natural question is "should we move to a different platform?" Almost always, no. Here's why: the security issues that actually breach production apps on Vercel aren't Vercel's fault. They're configuration decisions the developer made. NEXT_PUBLIC_ variables with secrets in them, preview deployments without access control, serverless function logs that capture PII, CSP headers that permit unsafe-inline. Those follow you to any host.

So rather than an incident post-mortem (Vercel's handling that), here's the actual audit: the seven Vercel-specific security issues we see in real apps every week. Fix these and your app is more secure than 90% of what ships to production, regardless of what happens at the platform level.

1. NEXT_PUBLIC_ Prefix Leaks

Critical Risk

The NEXT_PUBLIC_ prefix inlines env vars into the client bundle. One typo exposes a secret forever.

Next.js on Vercel uses a convention: environment variables prefixed with NEXT_PUBLIC_ get bundled into the client-side JavaScript so they're accessible in the browser. Everything else stays server-side only.

The failure mode: developers paste a secret into Vercel's env var UI, accidentally name it with the NEXT_PUBLIC_ prefix, and ship. Once deployed, the secret is in every user's browser. Removing it from the Vercel dashboard afterward doesn't help because the bundle is still cached and distributed.

// .env.local, the mistake

NEXT_PUBLIC_OPENAI_API_KEY=sk-proj-abc123...

NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_...

// Both are now in every client bundle

How to audit

  1. List every NEXT_PUBLIC_* var in your Vercel dashboard.
  2. For each one, ask: "Should every visitor be able to see this?" If the answer is no, the prefix is wrong.
  3. Any secret that ever had this prefix must be rotated. The bundle is out there.
  4. Use Route Handlers (app/api/*) or Server Actions for anything that touches a secret.

2. Preview Deployments Without Access Control

High Risk

Every PR creates a public URL. Every public URL is crawlable. Every crawlable URL ends up in search results.

Vercel generates a preview deployment for every git branch and pull request. By default, these URLs (yourapp-git-feature-branch-yourteam.vercel.app) are publicly accessible. They often contain unreleased features, partially-implemented admin panels, staging data, or debug output.

Preview URLs get into Google's index surprisingly often through tweets, Slack messages, Linear comments, or deployment notification webhooks that get crawled. Once indexed, your half-built feature is public.

How to fix it

  1. Enable Vercel Authentication for preview deployments (Settings, Deployment Protection).
  2. Or set up Shareable Links so only people with the link can access previews.
  3. Add X-Robots-Tag: noindex for preview environments to stop indexing.

3. Environment Variable Scope Mix-ups

High Risk

Production secrets available in Development and Preview scopes create leakage paths to untrusted environments.

Vercel lets you scope each env var to Production, Preview, Development, or any combination. The convenient move is to enable all three so "things just work." The risk: your production STRIPE_SECRET_KEY is now loaded in every preview deployment built from every branch, including ones from contractors or forks.

Preview deployments are less audited than production. A PR that adds console.log(process.env.STRIPE_SECRET_KEY) might slip through code review if the reviewer assumes that variable won't be defined in previews. On Vercel, it is, if you scoped it everywhere.

How to audit

  1. Go to Project, then Settings, then Environment Variables.
  2. For each production secret, verify it's NOT enabled for Preview or Development.
  3. Use separate test-mode keys (Stripe test keys, sandbox tokens) for Preview.

4. Serverless Function Log Leakage

Vercel's Functions tab shows logs for every invocation: request headers, query params, console output, and errors. Anyone with project access to Vercel can read these logs. If your functions log sensitive data (intentionally via console.log(user) or accidentally via uncaught errors that include session tokens), it ends up in the log retention window.

// Common pattern that leaks PII to Vercel logs

export async function POST(request: Request) {

const body = await request.json()

console.log('received:', body) // body includes password, PII, API keys...

// ...

}

How to fix

  1. Audit every console.log in Route Handlers for what it outputs.
  2. Use a logger that redacts sensitive fields by default (pino with redact, winston with a custom formatter).
  3. Catch errors explicitly. Don't let unhandled errors dump stack traces that may contain tokens.
  4. Restrict Vercel project access to people who actually need it.

5. Missing or Loose Security Headers

Vercel sets a few security headers by default (HSTS on production domains, X-Content-Type-Options for static files) but not everything you need. Content-Security-Policy, X-Frame-Options, Permissions-Policy, and Referrer-Policy all have to be configured manually, usually in next.config.js or vercel.json.

The most common failure isn't "no CSP," it's "CSP with unsafe-inline." A CSP that includes 'unsafe-inline' in script-src provides essentially no XSS protection. Many Next.js apps land there because getting a strict CSP working with Next's inline scripts takes deliberate nonce setup.

// next.config.js, strict-ish starter

async headers() {

return [{

source: '/(.*)',

headers: [

{ key: 'X-Frame-Options', value: 'DENY' },

{ key: 'X-Content-Type-Options', value: 'nosniff' },

{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },

{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },

]

}]

}

For CSP, use nonce-based configuration (Next.js docs) rather than unsafe-inline. Or test your existing CSP to see if it's actually protecting you.

6. CORS Misconfiguration in API Routes

Vercel Route Handlers and API routes need explicit CORS handling for cross-origin requests. The easy (and wrong) fix when developers hit a CORS error: set Access-Control-Allow-Origin: * to make the error go away. This often ships to production.

Worse patterns: reflecting the incoming Origin header back in the response, or accepting Origin: null. Both effectively disable the same-origin policy for your API.

How to check

Test your API with an attacker-like origin to see if it gets reflected. Or manually inspect your Route Handler headers. If you see Origin reflection with credentials, fix it immediately.

7. Build-Time Secret Leakage in Logs

Vercel's deployment logs are visible to every team member. If your build process console.logs environment variables (even for debugging), they get captured in the build output and retained. A common offender is CI scripts or custom build commands that echo environment state on failure.

Another pattern: using an env var in a shell command via $VAR interpolation in package.json scripts. Vercel's build logs show the fully-expanded command line, meaning the secret value appears literally in the log.

How to fix

  1. Review build logs for any env var values visible in plaintext.
  2. Remove any echo $SECRET or equivalent from build scripts.
  3. If a secret was ever in the logs, rotate it. Logs are retained and may have been viewed.

Why Platform Incidents Don't Change This List

Every time a hosting platform discloses an incident, the same conversation happens: should we be hosting somewhere else? The honest answer is almost always no.

Platform-level incidents are rare, visible, and acknowledged publicly. Application-layer issues (the seven above) are common, invisible, and entirely your responsibility. The overwhelming majority of real breaches on Vercel-hosted apps come from the second category, not the first. An app with perfect env scoping, locked-down previews, and strict CSP on AWS, Netlify, Vercel, or a VPS you manage yourself is more secure than an app with NEXT_PUBLIC_ secrets and no CSP on any of them.

Migrating hosts after a platform incident is expensive, risky, and doesn't fix the things that actually get apps breached. Running through a checklist like this one does.

Find These Issues in Your Vercel App

VAS scans your deployed Vercel app for every issue in this checklist: NEXT_PUBLIC_ leaks, missing headers, CORS misconfigs, exposed secrets, and more. You get a priority-ordered fix list in minutes.

Related Resources