[{"data":1,"prerenderedAt":424},["ShallowReactive",2],{"blog-guides/vercel":3},{"id":4,"title":5,"body":6,"category":403,"date":404,"dateModified":405,"description":406,"draft":407,"extension":408,"faq":409,"featured":407,"headerVariant":410,"image":409,"keywords":409,"meta":411,"navigation":412,"ogDescription":413,"ogTitle":409,"path":414,"readTime":415,"schemaOrg":416,"schemaType":417,"seo":418,"sitemap":419,"stem":420,"tags":421,"twitterCard":422,"__hash__":423},"blog/blog/guides/vercel.md","Vercel Security Guide: Environment Variables and Edge Functions",{"type":7,"value":8,"toc":384},"minimark",[9,16,21,24,59,63,66,130,144,149,163,172,176,179,188,197,201,212,221,225,228,239,243,248,251,254,257,260,264,268,277,281,290,294,298,301,304,307,310,313,316,319,322,325,353,372],[10,11,12],"tldr",{},[13,14,15],"p",{},"Vercel handles SSL, DDoS protection, and infrastructure security for you. Your job is managing environment variables correctly (NEXT_PUBLIC_ prefix exposes to browser), securing API routes with authentication, and configuring security headers. Use Vercel's preview deployments carefully since they share the same environment variables as production by default.",[17,18,20],"h2",{"id":19},"what-vercel-handles-for-you","What Vercel Handles for You",[13,22,23],{},"Vercel provides several security features automatically:",[25,26,27,35,41,47,53],"ul",{},[28,29,30,34],"li",{},[31,32,33],"strong",{},"SSL/HTTPS:"," All deployments get automatic SSL certificates",[28,36,37,40],{},[31,38,39],{},"DDoS protection:"," Built-in protection against denial of service attacks",[28,42,43,46],{},[31,44,45],{},"Edge network:"," Requests are handled at the edge, reducing attack surface",[28,48,49,52],{},[31,50,51],{},"Isolated functions:"," Serverless functions run in isolated environments",[28,54,55,58],{},[31,56,57],{},"Automatic updates:"," Infrastructure is maintained and patched by Vercel",[17,60,62],{"id":61},"environment-variables-the-most-common-mistake","Environment Variables: The Most Common Mistake",[13,64,65],{},"Vercel's environment variable handling is where most security issues occur. Understanding the naming convention is critical:",[67,68,69,85],"table",{},[70,71,72],"thead",{},[73,74,75,79,82],"tr",{},[76,77,78],"th",{},"Variable Name",[76,80,81],{},"Where It's Available",[76,83,84],{},"Safe for Secrets?",[86,87,88,100,111,120],"tbody",{},[73,89,90,94,97],{},[91,92,93],"td",{},"DATABASE_URL",[91,95,96],{},"Server-side only",[91,98,99],{},"Yes",[73,101,102,105,108],{},[91,103,104],{},"NEXT_PUBLIC_API_URL",[91,106,107],{},"Browser + Server",[91,109,110],{},"No (public)",[73,112,113,116,118],{},[91,114,115],{},"STRIPE_SECRET_KEY",[91,117,96],{},[91,119,99],{},[73,121,122,125,127],{},[91,123,124],{},"NEXT_PUBLIC_STRIPE_KEY",[91,126,107],{},[91,128,129],{},"Only publishable keys",[131,132,133],"danger-box",{},[13,134,135,138,139,143],{},[31,136,137],{},"Critical rule:"," Any variable starting with ",[140,141,142],"code",{},"NEXT_PUBLIC_"," is bundled into your frontend JavaScript and visible to anyone. Never put secrets in NEXT_PUBLIC_ variables.",[145,146,148],"h3",{"id":147},"common-environment-variable-mistakes","Common Environment Variable Mistakes",[150,151,153],"code-block",{"label":152},"WRONG: Secret with NEXT_PUBLIC prefix",[154,155,160],"pre",{"className":156,"code":158,"language":159},[157],"language-text","# This exposes your database password to the browser!\nNEXT_PUBLIC_DATABASE_URL=postgres://user:password@host/db\n\n# This exposes your secret API key!\nNEXT_PUBLIC_OPENAI_KEY=sk-abc123...\n","text",[140,161,158],{"__ignoreMap":162},"",[150,164,166],{"label":165},"CORRECT: Keep secrets without NEXT_PUBLIC",[154,167,170],{"className":168,"code":169,"language":159},[157],"# Server-side only (safe)\nDATABASE_URL=postgres://user:password@host/db\nOPENAI_API_KEY=sk-abc123...\n\n# Public variables (only non-secrets)\nNEXT_PUBLIC_APP_URL=https://myapp.com\nNEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...\n",[140,171,169],{"__ignoreMap":162},[17,173,175],{"id":174},"securing-api-routes","Securing API Routes",[13,177,178],{},"API routes in Next.js on Vercel are serverless functions. They need authentication:",[150,180,182],{"label":181},"Unprotected API route (vulnerable)",[154,183,186],{"className":184,"code":185,"language":159},[157],"// pages/api/users.js or app/api/users/route.js\nexport async function GET() {\n  // BAD: Anyone can access this\n  const users = await db.users.findMany();\n  return Response.json(users);\n}\n",[140,187,185],{"__ignoreMap":162},[150,189,191],{"label":190},"Protected API route (secure)",[154,192,195],{"className":193,"code":194,"language":159},[157],"// app/api/users/route.js\nimport { getServerSession } from 'next-auth';\n\nexport async function GET(request) {\n  // Check authentication\n  const session = await getServerSession();\n\n  if (!session) {\n    return Response.json({ error: 'Unauthorized' }, { status: 401 });\n  }\n\n  // Check authorization (e.g., admin only)\n  if (session.user.role !== 'admin') {\n    return Response.json({ error: 'Forbidden' }, { status: 403 });\n  }\n\n  const users = await db.users.findMany();\n  return Response.json(users);\n}\n",[140,196,194],{"__ignoreMap":162},[17,198,200],{"id":199},"security-headers-configuration","Security Headers Configuration",[13,202,203,204,207,208,211],{},"Add security headers in your ",[140,205,206],{},"next.config.js"," or ",[140,209,210],{},"vercel.json",":",[150,213,215],{"label":214},"next.config.js security headers",[154,216,219],{"className":217,"code":218,"language":159},[157],"/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  async headers() {\n    return [\n      {\n        source: '/(.*)',\n        headers: [\n          {\n            key: 'X-Content-Type-Options',\n            value: 'nosniff',\n          },\n          {\n            key: 'X-Frame-Options',\n            value: 'DENY',\n          },\n          {\n            key: 'X-XSS-Protection',\n            value: '1; mode=block',\n          },\n          {\n            key: 'Referrer-Policy',\n            value: 'strict-origin-when-cross-origin',\n          },\n          {\n            key: 'Content-Security-Policy',\n            value: \"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';\",\n          },\n        ],\n      },\n    ];\n  },\n};\n\nmodule.exports = nextConfig;\n",[140,220,218],{"__ignoreMap":162},[17,222,224],{"id":223},"preview-deployments-security","Preview Deployments Security",[13,226,227],{},"Vercel creates preview deployments for every git branch and PR. Security considerations:",[25,229,230,233,236],{},[28,231,232],{},"Preview deployments share environment variables with production by default",[28,234,235],{},"Preview URLs are public (though not easily guessable)",[28,237,238],{},"Consider using different environment variables for preview vs production",[145,240,242],{"id":241},"protecting-preview-deployments","Protecting Preview Deployments",[244,245,247],"h4",{"id":246},"preview-deployment-security-options","Preview Deployment Security Options",[13,249,250],{},"Enable Vercel Authentication for previews (Team/Enterprise)",[13,252,253],{},"Use different API keys for preview environment",[13,255,256],{},"Don't put sensitive test data in preview databases",[13,258,259],{},"Consider password protecting preview deployments",[17,261,263],{"id":262},"serverless-function-security","Serverless Function Security",[145,265,267],{"id":266},"input-validation","Input Validation",[150,269,271],{"label":270},"Validate all input in API routes",[154,272,275],{"className":273,"code":274,"language":159},[157],"import { z } from 'zod';\n\nconst UserSchema = z.object({\n  email: z.string().email(),\n  name: z.string().min(1).max(100),\n});\n\nexport async function POST(request) {\n  const body = await request.json();\n\n  // Validate input\n  const result = UserSchema.safeParse(body);\n  if (!result.success) {\n    return Response.json(\n      { error: 'Invalid input', details: result.error.issues },\n      { status: 400 }\n    );\n  }\n\n  // Use validated data\n  const { email, name } = result.data;\n  // ... process request\n}\n",[140,276,274],{"__ignoreMap":162},[145,278,280],{"id":279},"rate-limiting","Rate Limiting",[150,282,284],{"label":283},"Basic rate limiting with Vercel KV",[154,285,288],{"className":286,"code":287,"language":159},[157],"import { kv } from '@vercel/kv';\n\nexport async function POST(request) {\n  const ip = request.headers.get('x-forwarded-for') || 'unknown';\n  const key = `ratelimit:${ip}`;\n\n  // Get current count\n  const count = await kv.incr(key);\n\n  // Set expiry on first request\n  if (count === 1) {\n    await kv.expire(key, 60); // 60 second window\n  }\n\n  // Check limit\n  if (count > 10) { // 10 requests per minute\n    return Response.json(\n      { error: 'Rate limit exceeded' },\n      { status: 429 }\n    );\n  }\n\n  // Process request...\n}\n",[140,289,287],{"__ignoreMap":162},[17,291,293],{"id":292},"vercel-security-checklist","Vercel Security Checklist",[244,295,297],{"id":296},"before-going-live","Before Going Live",[13,299,300],{},"No secrets in NEXT_PUBLIC_ variables",[13,302,303],{},"All API routes have authentication checks",[13,305,306],{},"Security headers configured",[13,308,309],{},"Input validation on all endpoints",[13,311,312],{},"Rate limiting on sensitive endpoints",[13,314,315],{},"Preview deployments are protected or use test data",[13,317,318],{},"Environment variables are scoped correctly",[13,320,321],{},"Logs don't contain sensitive data",[13,323,324],{},"CORS configured appropriately",[326,327,328,335,341,347],"faq-section",{},[329,330,332],"faq-item",{"question":331},"Are my environment variables encrypted on Vercel?",[13,333,334],{},"Yes, Vercel encrypts environment variables at rest and in transit. They're securely injected into your functions at runtime. However, variables with the NEXT_PUBLIC_ prefix are bundled into your JavaScript and sent to browsers.",[329,336,338],{"question":337},"Can someone access my serverless function code?",[13,339,340],{},"No, your serverless function source code is not accessible to users. They can only interact with your functions through HTTP requests. The code runs in Vercel's secure infrastructure.",[329,342,344],{"question":343},"Should I worry about preview deployment URLs being discovered?",[13,345,346],{},"Preview URLs are random and hard to guess, but they are technically public. For sensitive projects, enable Vercel Authentication (available on Team/Enterprise plans) or use a password protection solution.",[329,348,350],{"question":349},"How do I rotate a compromised secret on Vercel?",[13,351,352],{},"Update the environment variable in Vercel Dashboard, then redeploy your application. The new value will be used immediately. Also rotate the credential with the original service (e.g., generate a new API key with your provider).",[354,355,356,362,367],"related-articles",{},[357,358],"related-card",{"description":359,"href":360,"title":361},"Full Next.js security guide","/blog/best-practices/nextjs","Securing Next.js Apps",[357,363],{"description":364,"href":365,"title":366},"Compare deployment platforms","/blog/comparisons/vercel-vs-netlify","Vercel vs Netlify Security",[357,368],{"description":369,"href":370,"title":371},"Platform security analysis","/blog/is-safe/vercel","Is Vercel Safe?",[373,374,377,381],"cta-box",{"href":375,"label":376},"/","Start Free Scan",[17,378,380],{"id":379},"deploying-to-vercel","Deploying to Vercel?",[13,382,383],{},"Scan your project for exposed secrets and security issues.",{"title":162,"searchDepth":385,"depth":385,"links":386},2,[387,388,392,393,394,397,401,402],{"id":19,"depth":385,"text":20},{"id":61,"depth":385,"text":62,"children":389},[390],{"id":147,"depth":391,"text":148},3,{"id":174,"depth":385,"text":175},{"id":199,"depth":385,"text":200},{"id":223,"depth":385,"text":224,"children":395},[396],{"id":241,"depth":391,"text":242},{"id":262,"depth":385,"text":263,"children":398},[399,400],{"id":266,"depth":391,"text":267},{"id":279,"depth":391,"text":280},{"id":292,"depth":385,"text":293},{"id":379,"depth":385,"text":380},"guides","2026-01-30","2026-02-23","Complete security guide for Vercel deployments. Learn to protect environment variables, secure serverless functions, and configure security headers for production.",false,"md",null,"blue",{},true,"Secure your Vercel deployments with proper secrets management and configuration.","/blog/guides/vercel","10 min read","[object Object]","Article",{"title":5,"description":406},{"loc":414},"blog/guides/vercel",[],"summary_large_image","Jr4SI7zmBE5E7JA0MsD1ADx11SnGfx6p-trBRyi2yyA",1775843918547]