Security Headers in vercel.json and netlify.toml: The 5-Minute Setup Most Developers Skip

Published December 28, 2025 ยท 8 min read

Security Headers in vercel.json and netlify.toml

Security headers tell browsers how to handle your site safely. Most Vercel and Netlify sites ship without them. Here's the exact configuration to add them in 5 minutes.

Why Security Headers Matter

Without security headers, your site is vulnerable to:

These headers are your first line of defense.

Quick Score Check

Before you start, check your current score:

  • Visit DomainOptic's Security Audit
  • Enter your domain
  • Look at your Security Headers grade
  • Most sites without configuration score D or F.

    Vercel Configuration

    Create or edit \vercel.json\ in your project root:

    \\\json

    {

    "headers": [

    {

    "source": "/(.*)",

    "headers": [

    {

    "key": "X-Content-Type-Options",

    "value": "nosniff"

    },

    {

    "key": "X-Frame-Options",

    "value": "DENY"

    },

    {

    "key": "X-XSS-Protection",

    "value": "1; mode=block"

    },

    {

    "key": "Referrer-Policy",

    "value": "strict-origin-when-cross-origin"

    },

    {

    "key": "Permissions-Policy",

    "value": "camera=(), microphone=(), geolocation=()"

    },

    {

    "key": "Strict-Transport-Security",

    "value": "max-age=31536000; includeSubDomains"

    }

    ]

    }

    ]

    }

    \\\

    Netlify Configuration

    Create or edit \netlify.toml\ in your project root:

    \\\toml

    [[headers]]

    for = "/*"

    [headers.values]

    X-Content-Type-Options = "nosniff"

    X-Frame-Options = "DENY"

    X-XSS-Protection = "1; mode=block"

    Referrer-Policy = "strict-origin-when-cross-origin"

    Permissions-Policy = "camera=(), microphone=(), geolocation=()"

    Strict-Transport-Security = "max-age=31536000; includeSubDomains"

    \\\

    What Each Header Does

    HeaderPurpose
    X-Content-Type-OptionsPrevents MIME-type sniffing attacks
    X-Frame-OptionsPrevents your site from being embedded in iframes (clickjacking)
    X-XSS-ProtectionEnables browser's XSS filter (legacy browsers)
    Referrer-PolicyControls how much referrer info is sent
    Permissions-PolicyRestricts which browser features can be used
    Strict-Transport-Security (HSTS)Forces HTTPS connections

    Adding Content-Security-Policy (CSP)

    CSP is the most powerful header but requires careful configuration. Start with a report-only policy:

    Vercel:

    \\\json

    {

    "key": "Content-Security-Policy-Report-Only",

    "value": "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:;"

    }

    \\\

    Netlify:

    \\\toml

    Content-Security-Policy-Report-Only = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:;"

    \\\

    Monitor your browser console for violations, then tighten the policy and switch to enforcing mode (\Content-Security-Policy\).

    Common CSP Additions by Service

    If you use these services, add them to your CSP:

    ServiceAdd to CSP
    Google Analytics\script-src https://www.googletagmanager.com\
    Google Fonts\font-src https://fonts.gstatic.com; style-src https://fonts.googleapis.com\
    Stripe\script-src https://js.stripe.com; frame-src https://js.stripe.com\
    Vercel Analytics\script-src https://va.vercel-scripts.com\
    Cloudflare\script-src https://static.cloudflareinsights.com\

    Testing Your Headers

    After deploying, verify your headers:

    Method 1: Browser DevTools
  • Open Network tab
  • Click on your main document request
  • Look at Response Headers
  • Method 2: Command Line

    \\\bash

    curl -I https://yoursite.com

    \\\

    Method 3: Automated Scan

    Use DomainOptic's Security Audit to check all headers at once.

    Complete Configuration Examples

    Vercel (production-ready):

    \\\json

    {

    "headers": [

    {

    "source": "/(.*)",

    "headers": [

    { "key": "X-Content-Type-Options", "value": "nosniff" },

    { "key": "X-Frame-Options", "value": "DENY" },

    { "key": "X-XSS-Protection", "value": "1; mode=block" },

    { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },

    { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" },

    { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains; preload" }

    ]

    }

    ]

    }

    \\\

    Netlify (production-ready):

    \\\toml

    [[headers]]

    for = "/*"

    [headers.values]

    X-Content-Type-Options = "nosniff"

    X-Frame-Options = "DENY"

    X-XSS-Protection = "1; mode=block"

    Referrer-Policy = "strict-origin-when-cross-origin"

    Permissions-Policy = "camera=(), microphone=(), geolocation=()"

    Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"

    \\\

    Deployment Checklist

  • Add configuration file (\vercel.json\ or \netlify.toml\)
  • Deploy to staging first
  • Test that your site still works (CSP can break things)
  • Check headers with curl or DevTools
  • Run security audit to verify grade improvement
  • Deploy to production
  • Key Takeaway

    Security headers are free, take 5 minutes to configure, and significantly improve your site's security posture. There's no reason not to add them. Copy the configuration above, deploy, and verify with a security scan.

    Check your security headers score -> Run a security audit