All posts

Is Your Vercel Preview Leaking Your Stripe Key? How to Check

Developer reaching for a glowing red padlock on a laptop screen in a dark office

Listen to this article

Picture a Slack message late on a Thursday night from someone reviewing your preview: “Hey, I can see your Stripe key. Should I?” You open the preview URL yourself, and there it is — sk_live_51... — sitting in the browser’s application tab, fully readable, fully spendable.

A Vercel preview deployment has just handed your production payment secret to anyone with the URL. The deployment was public by default, and nothing locked it down.

Why Vercel Preview Deployments Expose Secrets by Default

Vercel creates preview URLs for every push to a non-production branch. These URLs are accessible to anyone who has the link — or who guesses it. If your build process, client-side code, or source maps reference environment variables, those variables become visible in the preview. Vercel does not automatically strip NEXT_PUBLIC_ prefixed variables from preview builds. According to Vercel’s own documentation, preview environments inherit the same environment variable bindings as production unless you explicitly configure branch-level overrides.

This means a single misconfigured NEXT_PUBLIC_STRIPE_KEY or, worse, a NEXT_PUBLIC_API_SECRET lands in the browser’s JavaScript bundle for every visitor.

Definition: A Vercel Preview Deployment = a temporary, publicly accessible copy of your application created from a git branch, sharing environment variable access with production unless restricted.

How These Leaks Get Discovered

Usually by accident: someone reviews a new feature through the preview URL and happens to be technically literate enough to open Chrome DevTools and poke around. Most reviewers would never look — which makes this even more dangerous.

Here is a three-step process to catch exposed variables before sharing a preview link:

Step 1: Check the Build Output

Before the deployment even goes live, inspect what your build process logged. In the Vercel build logs, search for any output that prints variable names. If you use console.log(process.env) anywhere — even in a test file — it will surface in the build output.

Step 2: Inspect the Client Bundle

Open the preview URL in a browser. Open DevTools → Application → Local Storage. Then check the Sources or Network tab for any .js files that contain strings matching your secret prefixes (sk_live, sk_test, NEXT_PUBLIC_). A quick grep on the bundled JavaScript reveals leaks in seconds:

curl -s https://your-preview.vercel.app/_next/static/chunks/*.js | grep -oE 'sk_live_[A-Za-z0-9]+'

Step 3: Run a Secrets Scan on Source

Tools like gitleaks, trufflehog, or Vercel’s own vercel env ls command can surface variables that should never have been committed. Run gitleaks detect --source . --verbose locally before every push.

What a Full Inventory of Leaks Can Look Like

When you run the checklist above, the Stripe key may be only the most obvious problem. A typical inventory looks like this:

Variable Risk Level How It Leaked
NEXT_PUBLIC_STRIPE_KEY High (live key) Hardcoded in a config object read by client code
NEXT_PUBLIC_SENTRY_DSN Medium Included in error tracking initialization
NEXT_PUBLIC_API_URL Low Pointed to a staging endpoint with weaker auth
AWS_ACCESS_KEY_ID Critical Accidentally committed in .env.local and bundled

The AWS key is the dangerous one, especially if it has AdministratorAccess attached because “it was just for testing.” Vercel’s build process can copy it into the build output, and the preview deployment then serves it via a source map.

How to Fix Vercel Environment Variable Leaks

Here is the fix sequence, step by step.

1. Separate Public and Private Variables

Vercel distinguishes between variables available on the client (NEXT_PUBLIC_ prefix) and those only accessible server-side. Audit every variable and strip the prefix from anything that does not genuinely need to run in the browser. If a variable contains a key, token, or secret, it should never carry the NEXT_PUBLIC_ prefix.

2. Create Branch-Level Overrides

In the Vercel dashboard, navigate to Settings → Environment Variables. For each variable, set the scope to Production only. Do not allow Preview or Development to inherit production secrets. Use separate test keys (sk_test_...) for preview builds.

3. Add a Pre-Commit Hook

Install gitleaks as a pre-commit hook using the Husky framework:

npm install --save-dev gitleaks husky
npx husky add .husky/pre-commit "gitleaks detect --source . --staged"

This prevents secrets from ever reaching your git history.

4. Rotate Every Exposed Key Immediately

If a secret has been in a preview deployment, rotate it. Do not assume the URL was “probably not seen.” Assume full exposure. Rotate the Stripe key, the AWS credentials, and the Sentry DSN within an hour of discovery.

5. Set Up Vercel Authentication on Preview URLs

Vercel supports password protection and authentication for preview deployments. Enable it under Project Settings → Deployment Protection. Even if you fix the code, this adds a second layer — a visitor who somehow gets the URL still cannot access the app.

What Is the Actual Risk of Exposed Environment Variables?

Exposed secrets in a preview deployment carry the same risk as exposed secrets in production. A Stripe sk_live key allows unauthorized charges. An AWS key with broad permissions allows resource creation, data access, or even cryptomining. According to the 2024 Verizon Data Breach Investigations Report, 68% of breaches involve a human element — including misconfiguration and credential exposure. Your preview URL is public infrastructure with production keys bolted onto it.

Unlike a staging server behind a VPN, a Vercel preview URL has no network boundary. Anyone with the link — or anyone who brute-forces a predictable slug — gets full access to whatever the application serves.

How Does This Compare to Other Hosting Platforms?

Vercel is not uniquely vulnerable. Netlify, Railway, and Render all create preview deployments with environment variable inheritance. The difference is that Vercel’s NEXT_PUBLIC_ convention creates a false sense of security — developers assume the prefix means “safe for public,” when it actually means “will be shipped to the client bundle.” That distinction matters when your client bundle is served from a publicly accessible URL.

Platform Preview Auth by Default Branch-Level Env Overrides Client-Side Secret Risk
Vercel No (free tier) Yes High if NEXT_PUBLIC_ is overused
Netlify No Yes High with client-side JS
Railway Yes (paid) Yes Lower (container-based)
Render Yes Yes Lower (server-rendered default)

What You Should Do Right Now

If you host on Vercel, run the three-step inspection today — build logs, client bundle grep, and source scan. Do not wait for someone else to find your secrets for you. Rotate anything exposed. Lock your preview deployments behind authentication. And audit your NEXT_PUBLIC_ prefix usage across every project.

How Can You Prevent Future Exposure in Preview Deployments?

The prevention playbook is simple but requires discipline: never use production secrets in preview environments, scan every commit before it reaches git, and password-protect every preview URL. If your team ships custom software on Vercel and you want a structured security review of your deployment pipeline, Trove Deck can help.

#Vercel · #EnvironmentVariables · #DevOps · #Security · #IndieHackers · #SaaS · #WebDev · #Privacy