Direct Answer: Core Headers Array Syntax
Define the async headers() export in next.config.js to return an array of route-specific header objects. This Next.js next.config.js headers array setup requires a source regex pattern and a nested headers array containing key/value pairs. Routing-level injection operates independently of traditional reverse proxies, aligning with modern platform-native security practices outlined in Server & Platform Implementation Guides.
module.exports = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' }
]
}
];
}
};
Exact Configuration: Security Headers Implementation
Populate the headers array with production-grade security directives. Scope headers using exact regex sources to prevent unintended application to static assets or API endpoints. Avoid overlapping source patterns to eliminate build-time race conditions. For environment-specific overrides and cache-control integration, consult Vercel & Next.js Header Management.
Security Implications & Hardening Notes:
- HSTS Permanence:
max-age=31536000is cached permanently by browsers. Test withmax-age=60in staging before production deployment.includeSubDomainsrisks breaking non-HTTPS subdomains if misconfigured. - CSP Strict-Dynamic:
default-src 'self'blocks inline scripts. Implementstrict-dynamicwith server-generated nonces for dynamic JS execution. - Middleware Override:
middleware.tsNextResponse.next()headers overridenext.config.jsheaders on matched routes. Do not duplicate directives across layers. - Static Export Bypass:
output: 'export'completely ignoresheaders(). Requires CDN or edge-network header injection.
async headers() {
return [
{
source: '/api/(.*)',
headers: [
{ key: 'Content-Security-Policy', value: "default-src 'self'; script-src 'self' 'nonce-<generated>'" },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' }
]
},
{
source: '/_next/static/(.*)',
headers: [
{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' }
]
}
];
}
Diagnostic Commands & Verification
Headers are only injected during next build and next start. Running next dev bypasses the headers() export. Execute the exact diagnostic sequence below to verify injection before deployment.
# 1. Build and start production server
npm run build && npm start
# 2. Verify global security headers on root route
curl -sI http://localhost:3000 | grep -iE 'strict-transport|x-frame|x-content-type|content-security|referrer-policy|permissions-policy'
# 3. Verify scoped API headers
curl -sI http://localhost:3000/api/test | grep -iE 'content-security|permissions-policy'
Verification Notes:
- Confirm HTTP 200 responses. Next.js normalizes header casing; verify exact match in terminal output.
- Check browser DevTools > Network > Headers for
Provisional headers are shownwarnings, which indicate middleware or proxy conflicts. - Security implication: Missing
Strict-Transport-Securityon the initial request enables protocol downgrade attacks. Verify viacurl -sI -X GETto inspect the raw response before browser caching.
Edge Cases & Rollback Procedures
Next.js merges headers() with next.config.js redirects/rewrites. Conflicts with middleware.ts NextResponse.next() headers will override next.config.js values. Misconfigured HSTS or CSP will trigger browser lockouts.
Edge Cases:
- Middleware header precedence:
middleware.tsheaders overridenext.config.jsheaders for matched routes. - Static export (
output: 'export'):headers()is ignored; requires server-level or CDN header injection. - Regex source collisions:
/.*and/(.*)cause build warnings and unpredictable header application. Use precise path matching.
Rollback Steps:
- Comment out the
headers()array innext.config.js. - Run
rm -rf .nextto purge the build cache and prevent stale header injection. - Execute
npm run build && npm startto verify baseline response headers. - Re-deploy with minimal
X-Content-Type-OptionsandX-Frame-Optionsonly, then incrementally add CSP/HSTS after validation.