HOW TO SECURE VERCEL - SECURITY GUIDE | VIBEEVAL

Vercel Security Context

Vercel handles a lot of the platform layer — TLS, automatic HTTPS, basic DDoS scrubbing, edge networking. Your residual surface lives in: (1) what’s in the deployed bundle (env-var prefixes, accidentally-public secrets), (2) preview deployment URLs that bypass the auth gate on your custom domain, (3) serverless function configuration, and (4) headers / CORS / rewrites you control through vercel.json or next.config.js. The recurring incident shape is “preview URL works without auth, attacker finds it via the deployment list, all the auth-gated features are accessible.”

Security Checklist

1. Use the right env-var prefix per scope

Vercel exposes only NEXT_PUBLIC_* (Next.js) / VITE_* (Vite) / PUBLIC_* (Astro) to the browser. Everything else stays server-side. Audit your env vars in Project → Settings → Environment Variables — confirm secrets (Stripe key, OpenAI key, DB URL) do not have a public prefix. The bug ships when an AI tool suggests NEXT_PUBLIC_STRIPE_SECRET_KEY to “make it accessible from the page.”

2. Set per-environment values

Each env var has Production / Preview / Development scopes. Set distinct values per env — never share the production key with preview. Preview deploys can be reached by anyone with the URL; sharing prod keys with preview is a key leak waiting to happen.

3. Enable Deployment Protection on previews

Project → Settings → Deployment Protection (Pro plan): require Vercel auth, password, or shareable link to access preview / branch deploys. Without this, every git push creates a public URL — accessible to anyone who guesses or finds the URL — that has the full app, including all the routes you only meant production users to see.

4. Configure auth on every protected route

For Next.js App Router: auth() from @/auth at the top of every server action and route handler. For middleware-based gating: define matcher to cover every protected path, not just the obvious ones. Test by hitting /api/admin/foo from an incognito browser; should return 401.

5. Audit serverless function code

Each route in app/api/ and pages/api/ is internet-reachable. The first three lines of each handler must check the session. Add input validation (Zod) on the body. For long-running operations, set the function’s maxDuration explicitly so a malicious request can’t exhaust your monthly compute budget.

6. Enable Vercel Firewall

Project → Settings → Firewall: enable. Configure rate limits per route, IP allowlists for admin paths, and challenge rules for suspicious traffic. The Firewall sits in front of the function — it stops abusive traffic before it consumes function-execution time and your bill.

7. Configure security headers in vercel.json

{
  "headers": [{
    "source": "/(.*)",
    "headers": [
      { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains; preload" },
      { "key": "X-Frame-Options", "value": "DENY" },
      { "key": "X-Content-Type-Options", "value": "nosniff" },
      { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
      { "key": "Content-Security-Policy", "value": "default-src 'self'" }
    ]
  }]
}

Verify with the Security Headers Checker.

8. Audit redirects and rewrites

In vercel.json redirects / rewrites: avoid open-redirect patterns like /r?to=... that obey the query parameter. Stick to specific source → specific destination. Open redirects are phishing pivots — see SSRF / open redirect / OAuth.

9. Verify HTTPS on every domain

Vercel handles HTTPS automatically. For custom domains, confirm the cert covers all variants (example.com, www.example.com, any subdomains in use). Test by hitting http://yourdomain.com and confirming the redirect to https://.

10. Configure rate limiting per route

Vercel Firewall does platform-level rate limiting; for application-level (per-user, per-action) use a Redis-backed counter (@upstash/ratelimit or equivalent). Tighten on /login, /signup, /reset-password, /api/expensive. The default is no limit, which means credential stuffing and bill-running attacks are free.

11. Review deployment logs

Project → Deployments → [deployment] → Logs: review weekly for: 5xx error spikes, repeated 4xx auth errors, requests to routes you don’t recognize. Vercel logs are short retention by default — stream to your SIEM if compliance requires longer.

12. Configure team permissions

Team → Settings → Members: review quarterly. Owner / Member / Developer / Viewer. Anyone with Developer access can deploy and read env vars — keep the list small. Ex-team members lose access on removal but their sessions persist; rotate sensitive secrets after departure.

13. Enable audit logs

Team → Settings → Audit Log (Pro+): track deployments, env-var changes, member additions, OAuth integrations. Useful for incident response.

14. Audit Edge Functions

Edge Functions run in V8 isolates with a smaller API surface than Node — but the same security rules apply: validate inputs, check auth, never include secrets in URL params (which end up in logs), set CORS to your origin only.

15. Configure DNS security

For custom domains: enable DNSSEC at your registrar. Add CAA records limiting cert issuance to Let’s Encrypt (or your CA of choice) — prevents an attacker who compromises another CA from issuing a valid cert for your domain.

16. Review third-party integrations

Team → Integrations: every integration has a token. Audit periodically — disconnect ones you stopped using. Each unused integration is a credential that could be compromised independently of your Vercel account.

17. Configure cache headers carefully

For pages that include user-specific data: Cache-Control: private, no-store to prevent accidental caching at edge. For public pages: explicit Cache-Control: public, max-age=... is fine. The bug shape is a logged-in page accidentally cached at the edge and served to other users.

18. Audit CORS on API routes

For routes called from your own frontend: don’t add CORS headers (same-origin works without). For cross-origin: allowlist the specific domain, never * with credentials. See CORS credentials misconfig.

19. Run a security scan

The Vibe Code Scanner catches the AI-specific deploy-side patterns Vercel hosts: source maps in production, exposed .env.example with real values, the preview-URL-bypass mentioned above. The full VibeEval scan adds BOLA and webhook trust.

Free Self-Audit Suite

Five free scanners.

Vibe Coding Security Risk Guide

Full risk catalogue.

Solo Founder Pre-Launch Checklist

12 checks before launch.

Automate Your Security Checks

VibeEval scans your Vercel deployment against every category above plus 305 more probes. Findings ship as paste-ready prompts for your AI editor.

SCAN YOUR APP

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

START FREE SCAN