How to Fix API Key Exposure in Vercel Apps
Vercel apps commonly expose API keys through the NEXT_PUBLIC_ environment variable prefix or by hardcoding secrets in source files. This guide shows you how to find exposed keys, move them to proper server-side environment variables, and prevent future leaks.
Find security issues automatically before attackers do.
Follow These Steps
Find all exposed keys in your codebase
Search for hardcoded secrets and improperly prefixed environment variables.
# Find hardcoded keys
grep -rn "sk-\|sk_live\|secret_key" app/ lib/ src/ --include="*.ts" --include="*.tsx"
# Find secrets exposed via NEXT_PUBLIC_
grep -rn "NEXT_PUBLIC_.*SECRET\|NEXT_PUBLIC_.*KEY.*sk" .env* app/ lib/Rotate compromised keys
Any key in client-side code or with NEXT_PUBLIC_ prefix is in the browser bundle and compromised. Rotate immediately.
Configure Vercel environment variables properly
Add new keys to the Vercel dashboard without NEXT_PUBLIC_ prefix.
# Vercel Dashboard > Settings > Environment Variables
# Secret keys (server-side only):
# OPENAI_API_KEY = sk-proj-... (Production)
# STRIPE_SECRET_KEY = sk-live-... (Production)
# Public values (safe for browser):
# NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY = pk_live-...
# NEXT_PUBLIC_APP_URL = https://yourapp.comAccess secrets in API routes and Server Components only
Server-only env vars are available in API routes, Server Components, and Server Actions.
// app/api/payment/route.ts - Server-side
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
// app/page.tsx - Server Component
const data = await fetchWithSecret(process.env.API_KEY!)
// NEVER access server-only env vars in Client Components
// They will be undefined and your code will breakMark sensitive variables in Vercel dashboard
Enable the "Sensitive" flag on secret environment variables to hide their values in logs and the dashboard.
This prevents secrets from appearing in build logs, deployment logs, and team member dashboards.
Deploy and scan
Deploy your changes and run a VAS scan to verify no secrets appear in the client bundle.
Use browser DevTools > Sources > search to verify no secret patterns exist in the client JavaScript.
What You'll Achieve
All API secrets are stored as server-only Vercel environment variables without the NEXT_PUBLIC_ prefix. Secret keys are only accessible in API routes and Server Components. The browser bundle contains no sensitive credentials.
Common Mistakes to Avoid
Mistake
Using NEXT_PUBLIC_ prefix for secret API keys
Fix
NEXT_PUBLIC_ embeds the variable in the client JavaScript bundle. Never use it for secrets. Server-side env vars (without prefix) are only available in server code.
Mistake
Setting env vars in .env.local but not in Vercel dashboard
Fix
Local .env files do not deploy to Vercel. Add all production secrets in the Vercel dashboard.
Mistake
Not using separate keys for Preview and Production
Fix
Use test/sandbox API keys for Preview deployments to prevent staging from affecting production data or billing.
Frequently Asked Questions
What does NEXT_PUBLIC_ do to my environment variables?
The NEXT_PUBLIC_ prefix tells Next.js to embed the variable value in the client JavaScript bundle. Anyone can see it in the browser. Never use this prefix for secrets.
Can I use process.env in client components?
Only NEXT_PUBLIC_ prefixed variables are available in client components. Server-only variables return undefined in client code. This is a security feature, not a bug.
Are Vercel environment variables encrypted?
Yes. Vercel encrypts environment variables at rest and in transit. They are injected into serverless functions at runtime and never included in the static build output unless prefixed with NEXT_PUBLIC_.
Ready to Secure Your App?
VAS automatically scans your deployed app for the security issues covered in this guide. Get actionable results in minutes.
Start Security Scan