HTTP security headers are instructions your server sends to the browser before any content loads. They tell the browser what it is and is not allowed to do on your page. They cost nothing to implement and protect against an entire class of attacks.
Here are the six headers every production website must have:
1. X-Frame-Options: DENY
Prevents your site from being embedded in an iframe on any other domain. Without this, attackers can load your site invisibly behind a fake UI and trick users into clicking things — a technique called clickjacking. Set it to DENY unless you specifically need to embed your own pages (in which case use SAMEORIGIN).
2. X-Content-Type-Options: nosniff
Tells the browser to trust the Content-Type header and never guess file types. Without it, a browser might execute a text file as JavaScript if the server sends the wrong MIME type — a MIME confusion attack. This one header closes that entire attack surface.
3. Strict-Transport-Security (HSTS)
Forces the browser to always use HTTPS for your domain, even if a user types http:// in the address bar. Set max-age to at least 31536000 (one year) and include the includeSubDomains and preload flags. Once set, man-in-the-middle HTTP downgrade attacks become impossible.
4. Referrer-Policy: strict-origin-when-cross-origin
Controls what URL information is sent in the Referer header when users click links from your site. Without this, the full URL — including any tokens, IDs, or sensitive query parameters — is leaked to every external resource your page loads.
5. Permissions-Policy
Disables browser features your site does not use. Explicitly deny camera, microphone, geolocation, payment, and USB access. If a malicious script is ever injected into your page, it cannot access these hardware features even if it tries.
6. Content-Security-Policy (CSP)
The most powerful header on this list — and the most complex. CSP is a whitelist: you tell the browser exactly which origins are allowed to load scripts, styles, images, fonts, and API connections. Anything not on the whitelist is blocked, even if it is injected by a compromised third-party script.
In Next.js, you add all six in next.config.ts under the headers() function. Apply them to all routes except your CMS studio path, which has its own requirements.