Netlify

Netlify Security Best Practices

Secure your Netlify site. From build-time variable exposure to Netlify Functions authentication and deploy context isolation.

Verify your app follows these best practices automatically.

Netlify's build pipeline creates a unique security distinction: variables used during build get embedded in your static output, while runtime variables only work in Netlify Functions. Mixing these up is the most common Netlify security mistake. Deploy contexts (Production, Deploy Preview, Branch Deploy) add another layer — each can have different secrets, but only if you configure them. These practices cover Netlify-specific risks.

Quick Wins

Check if any secrets are used in build commands or frontend code (they'll be in static output)
Try calling each Netlify Function URL without authentication — verify they return 401
Create a _headers file with basic security headers (X-Frame-Options, X-Content-Type-Options)
Review deploy context configuration in netlify.toml for production secret isolation
Check which Netlify plugins are installed and what permissions they need

Security Best Practices

#1Separate Build-Time and Runtime Variables

critical

Netlify has two types of environment variables: build-time (available during build, embedded in output) and runtime (only in Netlify Functions). Secrets used during build end up in your static files.

Implementation

Use build-time variables only for public config. Keep secrets in runtime-only variables accessed through Netlify Functions.

Don't do this
# Used during build — embedded in static HTML/JS output
STRIPE_SECRET_KEY=sk_live_abc123
Do this instead
# Build-time (public only)
SITE_URL=https://mysite.com

# Runtime only (Netlify Functions)
# Set in Dashboard with 'Functions' scope
STRIPE_SECRET_KEY=sk_live_abc123

#2Add Authentication to Every Netlify Function

critical

Netlify Functions are accessible at /.netlify/functions/<name>. There's no built-in auth — anyone who knows the URL can call them. Each function must validate the caller.

Implementation

Check JWT or session token at the start of every function. Return 401 immediately if invalid.

#3Use Deploy Contexts for Secret Isolation

critical

Netlify lets you set different variable values per deploy context (Production, Deploy Preview, Branch Deploy). Without this, preview deployments use production secrets.

Implementation

In netlify.toml, set context-specific variables. Use staging API keys for deploy-preview context.

#4Configure Headers via _headers File

high

Netlify serves static sites from a CDN — you can't set headers in application code. Use the _headers file or netlify.toml to add security headers.

Implementation

Create a _headers file in your publish directory with CSP, HSTS, X-Frame-Options, and X-Content-Type-Options

Don't do this
# No _headers file = no security headers on your static site
Do this instead
# _headers (in publish directory)
/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Strict-Transport-Security: max-age=31536000
  Content-Security-Policy: default-src 'self'

#5Restrict Deploy Preview Access

high

Every PR creates a public deploy preview URL. For sites with sensitive content, enable access controls to prevent preview leaks.

Implementation

Use Netlify Identity or password protection for preview deployments in Site Settings

#6Audit Netlify Plugins for Security

medium

Netlify plugins run during build with access to your environment variables and file system. Third-party plugins can exfiltrate secrets.

Implementation

Only use well-maintained plugins with public source code. Review what environment variables each plugin accesses.

Common Mistakes to Avoid

Using secrets in build-time variables

Why it's dangerous:

Build-time variables get embedded in static HTML/JS output, visible to all users

How to fix:

Keep secrets in runtime-only variables and access them through Netlify Functions

Netlify Functions without authentication

Why it's dangerous:

Functions are public endpoints at /.netlify/functions/<name> — no built-in auth protection

How to fix:

Validate JWT or session token at the start of every function before processing

No deploy context isolation

Why it's dangerous:

Preview deployments use production API keys by default, meaning PRs can modify production data

How to fix:

Configure context-specific variables in netlify.toml so previews use staging resources

Verify Your Netlify App Security

Following best practices is the first step. Verify your app is actually secure with a comprehensive security scan.

Get Starter Scan

Frequently Asked Questions

What's the difference between build-time and runtime variables on Netlify?

Build-time variables are available during the build process and get embedded in your static output — anyone can see them in the HTML/JS. Runtime variables are only accessible in Netlify Functions and never appear in static files. Always use runtime variables for secrets.

How do I add security headers on Netlify?

Create a _headers file in your publish directory (usually 'public/' or 'dist/'). Add headers with path patterns. Unlike server-based platforms, you can't set headers in application code since Netlify serves static files from a CDN.

How is Netlify security different from Vercel?

Netlify's biggest risk is the build-time vs runtime variable distinction — build variables get embedded in static output. Vercel's equivalent risk is the NEXT_PUBLIC_ prefix. Netlify Functions need explicit auth (no built-in middleware), while Vercel has Edge Middleware. Both need preview protection but use different mechanisms.

Last updated: January 2026