pwnmyvibecode_

Is your Vercel app safe?

Vercel is a secure host: HTTPS, certificates and the edge network are handled for you. Your app is safe when secrets stay out of NEXT_PUBLIC_ variables, your server routes check who is calling, and you set the security headers Vercel does not add for you.

Updated

Check your live site now

Free, no signup, read only. A grade and plain fixes in seconds.

What Vercel secures, and what you still own

Vercel issues certificates, redirects http to https, runs your server code in isolated functions and stores environment variables encrypted. Each deployment is immutable, so a bad deploy can be rolled back.

What you own is the code and config you deploy. Vercel does not choose your Content-Security-Policy. It cannot stop a Next.js build from inlining a secret you named NEXT_PUBLIC_. It does not know whether your API route should check a session before returning data.

Security mistakes Vercel apps commonly make

  • A secret key in a NEXT_PUBLIC_ variable. Next.js replaces those at build time, so the value sits in a JavaScript file served to every visitor.
  • A client component that needs an API, so the key gets renamed with NEXT_PUBLIC_ to make it work, instead of moving the call to a route handler or server action.
  • No Content-Security-Policy, no frame protection and no Referrer-Policy.
  • Route handlers and server actions that trust whatever the browser sends and never check the session.
  • Auth cookies set without Secure or HttpOnly by hand-rolled login code.
  • Preview deployments with public URLs that use production environment variables and the production database.
  • CORS headers that echo back any origin with credentials allowed.

Where the fixes go on Vercel

Headers can go in vercel.json for any framework. In a Next.js app, the headers() function in next.config.ts works too and keeps the config with your code. This is the vercel.json version:

vercel.json
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Strict-Transport-Security",
          "value": "max-age=31536000; includeSubDomains"
        },
        {
          "key": "Content-Security-Policy",
          "value": "default-src 'self' https: data: blob: 'unsafe-inline' 'unsafe-eval'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'; upgrade-insecure-requests"
        },
        {
          "key": "X-Frame-Options",
          "value": "SAMEORIGIN"
        },
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        },
        {
          "key": "Referrer-Policy",
          "value": "strict-origin-when-cross-origin"
        },
        {
          "key": "Permissions-Policy",
          "value": "camera=(), microphone=(), geolocation=()"
        }
      ]
    }
  ]
}

Secrets go in Project Settings, Environment Variables, without the NEXT_PUBLIC_ prefix. Vercel lets you mark a variable as sensitive so its value cannot be read back in the dashboard. Scope values per environment, so previews use a test database and test keys.

Preview URLs can be protected with Vercel's Deployment Protection. Check whether it is on for your project if previews connect to anything real.

prompt for your agent
This app is deployed on Vercel. Find every NEXT_PUBLIC_ environment variable and tell me which ones hold secrets. For each one, move the code that uses it into a route handler or server action and read the key from process.env without the prefix. Add security headers (HSTS, a Content-Security-Policy that fits this app, X-Frame-Options, X-Content-Type-Options, Referrer-Policy) in next.config.ts. Make sure every route handler and server action that touches user data checks the session first.

Vercel security checklist

  1. List every NEXT_PUBLIC_ variable in Vercel and in your .env files. None should be a secret.
  2. Rotate any secret that was ever public, then remove the prefix and move its use server side.
  3. Add security headers in vercel.json or next.config.ts, redeploy, and confirm them with curl.
  4. Check that each route handler and server action verifies the user before reading or writing their data.
  5. Set session cookies with Secure, HttpOnly and SameSite.
  6. Give preview and production separate secrets and databases, and turn on Deployment Protection for previews.

How to verify your live Vercel app

terminal
curl -sI https://yourapp.vercel.app | grep -iE 'strict-transport|content-security|x-frame|x-content-type|referrer-policy|set-cookie'

To look for leaked secrets yourself, open DevTools, Sources, and search the files under _next/static for sk_live_, sk-, AKIA and service_role. You should find none.

An outside scan runs those checks in one go: secret keys in the HTML and your own JavaScript bundles, public .env and .git files, each security header including how strict the CSP is, the https redirect, cookie flags and CORS. It does not log in or call your API routes with test data, so it cannot tell whether a route checks the session. Review that in the code, or ask your agent to list each route and the check it performs.

Questions

Is Vercel safe for production apps?

Yes. The platform side, meaning HTTPS, isolation and encrypted environment variables, is handled. The app side, meaning what you expose and how routes check access, is yours.

Are Vercel environment variables visible to users?

Not unless your framework inlines them. In Next.js, anything named NEXT_PUBLIC_ is written into the client bundle at build time. Everything else stays on the server.

Should I set headers in vercel.json or next.config.ts?

Either works on Vercel. next.config.ts keeps headers with your code and also works if you move hosts. A nonce-based CSP needs to be set per request in Next.js code, not in a static config file.

Does Vercel add security headers automatically?

It handles HTTPS, but it does not write a Content-Security-Policy or frame protection for you. Check your live response headers to see what you are actually sending.