VERCEL SECURITY CHECKLIST

Vercel’s strength — every PR gets a public preview URL, env vars are scoped per environment, edge functions run close to the user — is also its security risk. Three patterns matter most: NEXT_PUBLIC_* env vars inline into the bundle (catching real secrets that should be server-only), preview deployments expose unfinished work to anyone with the URL, and edge functions with broad network access become SSRF vectors. The checklist below is what we look for first when we audit a Vercel deployment.

Treat Critical as launch-blocking. High is week-one. Medium is the cleanup once you have users.

How to use this checklist

Walk it once in the Vercel dashboard for your production project, ticking items as you go. After each fix, deploy a preview and re-test against the preview URL — preview-specific issues won’t surface in production until a developer accidentally promotes a preview-shaped config. After the whole list passes, run a black-box scan against the production domain and a recent preview.

Critical (fix before launch)

1. Move secrets out of NEXT_PUBLIC_* and VITE_* env vars

Why it matters. Next.js inlines anything prefixed NEXT_PUBLIC_ (and Vite inlines VITE_*) into the client bundle at build time. The string process.env.NEXT_PUBLIC_STRIPE_KEY becomes a literal in the JavaScript that ships to every browser. AI coding tools default to NEXT_PUBLIC_* because it “just works” without server routes.

How to check. In Vercel dashboard → Settings → Environment Variables, list every NEXT_PUBLIC_* and VITE_* var. Confirm each is a value that’s intentionally public (publishable Stripe key, public Supabase URL, anon key). Then curl https://your-app.vercel.app/_next/static/chunks/*.js | grep -E '(sk_|rk_|sk-proj-|re_)' to find leaks.

How to fix. Move secret-bearing API calls to a server action, route handler, or middleware. Reference secrets via process.env.X (no NEXT_PUBLIC_). Rotate any value that ever sat in a NEXT_PUBLIC_ var.

2. Configure environment scoping correctly

Why it matters. Vercel scopes env vars to Production / Preview / Development. The default for new vars is “all environments” — meaning preview deployments read your production secrets. A preview URL leaked publicly with prod secrets in env is functionally a credential breach.

How to check. Settings → Environment Variables. For every secret, confirm it’s scoped to Production only (and Development for local work). Preview should have its own staging-equivalent values.

How to fix. Re-scope. For each production secret, create separate Preview values pointing at staging resources. Confirm by deploying a preview and inspecting which env values it received.

3. Set Vercel Authentication on previews

Why it matters. Preview URLs are publicly reachable by default. Search engines crawl them; competitors find them; the URLs leak via PR descriptions and Slack. Vercel Authentication gates previews behind your team’s SSO.

How to check. Settings → Deployment Protection. Confirm Vercel Authentication is on for preview deployments.

How to fix. Enable Vercel Authentication for previews. For private projects, also enable for production until launch day.

4. Audit Edge Functions for SSRF

Why it matters. Edge Functions have full outbound network access. A function that takes a URL from the request and fetch()es it — for OG images, link previews, webhook tests, RSS readers — is a textbook SSRF, including against cloud metadata endpoints (http://169.254.169.254/).

How to check. Search Edge Function code for fetch(req.body.url), fetch(searchParams.get('url')), and similar patterns. Test with http://localhost, http://169.254.169.254/, file:///etc/passwd.

How to fix. Validate URLs against an allowlist (specific hosts) or reject private IP ranges and link-local addresses explicitly. For OG-image fetches, use a hardened image proxy.

5. Verify deployed branch protection rules

Why it matters. Vercel can deploy any branch to production if the project is configured that way. We have audited cases where a developer pushed directly to main and Vercel auto-shipped their unfinished PR to production.

How to check. Settings → Git. Confirm production deploys come from your protected branch only. In GitHub, confirm branch protection requires PR review.

How to fix. Restrict Vercel production deploys to the protected branch. Require PR review for the protected branch.

6. Confirm middleware actually runs on protected routes

Why it matters. Next.js middleware runs based on the matcher config. AI-generated middleware sometimes has a matcher that excludes the routes it was supposed to protect — passing tests because the matcher is wrong, not because the auth check is.

How to check. Read middleware.ts. For every protected path, confirm the matcher actually matches it. Test by making a request to a protected route with no auth cookie and confirming a 401 / redirect.

How to fix. Tighten the matcher. Add a unit or integration test per protected route asserting the middleware fires.

High (fix in the first week)

7. Enable Vercel WAF rules on production

Vercel’s WAF (Pro+) catches common attacks — SQL injection patterns, command injection, path traversal. Enable the managed ruleset and tune rules that flag legitimate traffic.

8. Configure rate limiting via middleware

Vercel doesn’t add rate limiting by default. Use @upstash/ratelimit in middleware to throttle public routes, especially auth, password reset, and any LLM-calling endpoint.

9. Pin Node.js runtime version

In package.json and vercel.json, pin the Node version explicitly. Auto-upgrades through major versions can change crypto, HTTP client behavior, and security defaults.

10. Restrict deploy hooks to required services

Deploy hooks are URLs that trigger redeployment when called. Audit which services have them; restrict scope; rotate after team changes.

11. Verify ISR-cached pages don’t include user-specific data

revalidate caches the rendered HTML. If the page includes the signed-in user’s data, every visitor sees the previous user’s data until the cache rotates. Move user-specific rendering to dynamic, or scope the cache key to the session.

12. Configure Edge Function secrets via env vars, not request bodies

Edge Functions sometimes get secrets passed in via the request body for “flexibility”. Move secrets to env vars; reject any request that tries to provide them.

Medium (fix when you can)

13. Set up Vercel Analytics PII redaction

Confirm Analytics and Speed Insights are not capturing PII in URL parameters or referrers. Configure server-side filtering if necessary.

14. Configure CSP and security headers in next.config.js

Vercel doesn’t add CSP, HSTS, or X-Frame-Options by default. Add them via headers() in next.config.js.

15. Restrict team member access by role

Settings → Team Members. Audit who has Owner / Member / Viewer. Owners can change any setting (including env vars and deploy targets). Downgrade where you can.

16. Audit installed Vercel integrations

Each integration (Stripe, Sentry, Datadog) has scopes. Audit; remove unused.

17. Verify domain DNS is locked

Domain hijacking is a thing. Lock DNS at the registrar level. Audit who has access to change DNS.

18. Set up alerting on deploy frequency anomalies

A sudden spike in deploys (especially overnight) signals a compromise of a deploy hook or a developer account. Alert on outliers.

After every config change

  • Re-test a preview URL — confirm authentication and env scoping behave as expected.
  • Re-verify production env vars haven’t drifted.
  • Re-confirm middleware matcher covers all protected routes.

Common attack patterns we see in Vercel deployments

The NEXT_PUBLIC_ Stripe key. Developer typed process.env.NEXT_PUBLIC_STRIPE_KEY because the AI suggested it. Live key shipped in bundle; charges fraud-bot transactions before someone notices.

The shared preview env. Preview deployments inherit production env. Preview URL leaks via Slack; attacker reads the production database token from the preview’s bundle.

The OG-image SSRF. Edge function fetches ?url= for OG previews. Attacker passes the AWS metadata URL, gets back IAM credentials.

The auto-deployed branch. Developer pushed a “WIP, do not deploy” branch to main because the project auto-deploys main. Half-broken auth shipped to production.

How to Secure Vercel

Step-by-step guide for hardening a Vercel project — env scoping, preview gating, middleware patterns, and the WAF setup above in long form.

Is Vercel Safe?

In-depth analysis of Vercel’s defaults — what’s locked down, what’s exposed, and what we find when we audit a typical Vercel-deployed app.

Automate Your Checklist

A checklist tells you what to look for. A scanner tells you what’s actually broken in the deployed app right now. VibeEval drives a real browser through your Vercel deployment, attempts the SSRF and bundle-leak attacks above, and reports what got through — with file and config to fix.

SCAN YOUR DEPLOYMENT

14-day trial. No card. Results in under 60 seconds.

START FREE SCAN