Next.js Security Headers: The Complete 2026 Checklist
Most Next.js apps ship with zero security headers. Here's the exact config to add to next.config.mjs — copy, paste, deploy.
Why security headers matter
Security headers are HTTP response headers that tell the browser how to behave when handling your site's content. They're one of the cheapest security wins available — a few lines of config that prevent entire classes of attacks like XSS, clickjacking, and MIME sniffing.
Fewer than 30% of websites have them correctly configured. For AI-built apps, the number is even lower — AI coding tools almost never add security headers unless explicitly asked.
Tools like SecurityHeaders.com grade your headers from A+ to F. Most vibe-coded apps score an F.
The complete Next.js security headers config
Add this to your next.config.mjs:
const securityHeaders = [
{
key: 'X-DNS-Prefetch-Control',
value: 'on'
},
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload'
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN'
},
{
key: 'X-Content-Type-Options',
value: 'nosniff'
},
{
key: 'Referrer-Policy',
value: 'strict-origin-when-cross-origin'
},
{
key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=()'
},
{
key: 'Content-Security-Policy',
value: [
"default-src 'self'",
"script-src 'self' 'unsafe-eval' 'unsafe-inline'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' blob: data: https:",
"font-src 'self'",
"object-src 'none'",
"base-uri 'self'",
"form-action 'self'",
"frame-ancestors 'none'",
"upgrade-insecure-requests",
].join('; ')
},
]
const nextConfig = {
async headers() {
return [
{
source: '/(.*)',
headers: securityHeaders,
},
]
},
}
export default nextConfigWhat each header does
Strict-Transport-Security (HSTS)
Forces browsers to use HTTPS for your domain for the next 2 years. Prevents SSL stripping attacks where an attacker downgrades your connection to HTTP. The preload flag submits your domain to browser preload lists.
Content-Security-Policy (CSP)
The most powerful header. Tells the browser which sources are allowed to load scripts, styles, images, and other resources. Prevents XSS attacks by blocking inline scripts from untrusted sources.
⚠️ Note: The config above uses unsafe-inline and unsafe-eval for compatibility with Next.js. For maximum security, use nonces instead — but this requires more setup.
X-Frame-Options
Prevents your site from being embedded in an iframe on another domain. Stops clickjacking attacks where an attacker overlays your site with a transparent iframe to steal clicks.
X-Content-Type-Options
Prevents browsers from MIME-sniffing a response away from the declared content type. Stops attacks where a malicious file is uploaded and served as a different type.
Referrer-Policy
Controls how much referrer information is included with requests. strict-origin-when-cross-origin sends the full URL for same-origin requests but only the origin for cross-origin — preventing leaking of sensitive URL parameters.
Permissions-Policy
Controls which browser features your site can use. Disabling camera, microphone, and geolocation prevents malicious scripts from accessing them even if injected.
Headers for apps using external services
If your app uses Razorpay, Google Fonts, Supabase, or other external services, you need to add them to your CSP:
// CSP for a typical Next.js + Supabase + Razorpay app "script-src 'self' 'unsafe-eval' 'unsafe-inline' https://checkout.razorpay.com", "frame-src 'self' https://api.razorpay.com", "connect-src 'self' https://*.supabase.co wss://*.supabase.co https://api.razorpay.com", "img-src 'self' blob: data: https:", "font-src 'self' https://fonts.gstatic.com", "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
How to verify your headers are working
After deploying, check your headers with:
curl -I https://your-app.vercel.app
Or use the free Vezraa Header Checker to get a graded report with specific recommendations.
Check your security headers — free, instant results.
Check Headers Free →