Security
Security headers check
Five response headers do most of the work of protecting a website's visitors in the browser. Here is what each one does, a safe value to start from, and how to set them.
Check your site's headers
Free, no account. We grade these five headers, look for secret keys in the page's code and cookies without their protections, and list every error on five of your pages.
Strict-Transport-Security
Tells browsers to use https for your site for a given time, even if someone types or follows an http:// link. Without it, a visitor's first request can go out over plain http, where a network in the middle can redirect or read it.
Strict-Transport-Security: max-age=31536000; includeSubDomains
Send this value only once every subdomain serves https, because browsers will then refuse http on all of them for a year. If unsure, start with a short max-age.
Content-Security-Policy
Lists where scripts, styles, images and connections may come from. If an attacker manages to inject a script tag (through a comment field, a compromised plugin), the browser refuses to run it because its source is not on the list.
Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com; img-src 'self' data: https:; frame-ancestors 'none'
This is the hardest one to get right, because a strict policy breaks anything you left off the list. Ship it first as Content-Security-Policy-Report-Only, read what it would have blocked, then enforce it.
Framing protection (X-Frame-Options or frame-ancestors)
Stops other sites from showing yours inside a hidden frame and tricking visitors into clicking buttons they cannot see (clickjacking).
X-Frame-Options: DENY # or, in the Content-Security-Policy: frame-ancestors 'none'
Use SAMEORIGIN (or frame-ancestors 'self') if your own site frames its pages.
X-Content-Type-Options
Stops the browser guessing a file's type from its contents. Without it, an uploaded file that looks like a script can be run as one.
X-Content-Type-Options: nosniff
Safe to add everywhere, as long as your server sends correct content types (JavaScript as text/javascript).
Referrer-Policy
Controls how much of your page's address other sites see when a visitor follows a link or loads an image from them. Addresses can carry tokens, emails or search terms.
Referrer-Policy: strict-origin-when-cross-origin
This is also the browser's default today; setting it makes it explicit and stops an older default applying.
How to set them
Wherever your site is served from, headers are one block of configuration.
# nginx, in the server block
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Next.js, next.config.js
async headers() {
return [{ source: "/(.*)", headers: [
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "X-Frame-Options", value: "DENY" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
] }];
}
# Netlify, a _headers file at the site's root
/*
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
# Vercel (any framework): "headers" in vercel.json, same shape as Next.js
# Cloudflare: Rules → Transform Rules → Modify Response HeaderHeaders are one part
The leaks that cost the most have nothing to do with headers: a secret key shipped in the page’s JavaScript, a database open to anyone with its public key, an API route that does not check who is calling. The web app security checklist covers them.