Outrings
Security and email authentication

What are security headers and which do I need?

Six headers, what each actually prevents, and a configuration you can paste and adjust.

3 min read
Short answer

Security headers are HTTP response headers that tell the browser to enforce restrictions on your behalf. Six matter for most sites: HSTS, Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, frame protection, and Permissions-Policy. All are free and most take one line.

Why they exist

A browser will do almost anything a page asks — load a script from anywhere, submit a form anywhere, render your page inside someone else's frame. Security headers are how you tell it not to. They cost nothing, they are enforced by the browser, and they turn whole classes of attack into non-events.

The six

Strict-Transport-Security

Strict-Transport-Security: max-age=31536000; includeSubDomains

Tells the browser to use HTTPS for this domain for the next year, without asking. This closes the window where a first request over HTTP could be intercepted before your redirect fires. Add preload and submit to the preload list to close it even on a first visit — but understand that preload is difficult to reverse, so be sure HTTPS works on every subdomain first.

Content-Security-Policy

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'

The most powerful and the most work. It declares where resources may come from, so an injected script from an unapproved origin simply does not run. Start in report-only mode, watch the violations, then enforce.

X-Content-Type-Options

X-Content-Type-Options: nosniff

Stops the browser guessing content types. Without it, a file you serve as text can be interpreted as JavaScript under the right conditions. One line, no downside, always add it.

Referrer-Policy

Referrer-Policy: strict-origin-when-cross-origin

Controls how much of the current URL is sent when a user follows a link out. Without it, a URL containing a token or a private identifier is handed to whatever site they clicked through to.

Frame protection

Content-Security-Policy: frame-ancestors 'self'
# or the older equivalent
X-Frame-Options: SAMEORIGIN

Prevents your page being embedded in someone else's, which is how clickjacking works. frame-ancestors is the modern form; sending both is fine for older browsers.

Permissions-Policy

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

Turns off browser features you do not use, so an injected script cannot reach for them.

A baseline to start from

# Apache / LiteSpeed
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header set X-Content-Type-Options "nosniff"
Header set Referrer-Policy "strict-origin-when-cross-origin"
Header set X-Frame-Options "SAMEORIGIN"
Header set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Add CSP last and add it carefully. It is the header most likely to break a working site, because almost every site loads something from somewhere it forgot about. Deploy it as Content-Security-Policy-Report-Only first, collect violations for a week, then enforce the policy you have verified.

Headers no longer worth setting

  • X-XSS-Protection — the filter it controlled has been removed from browsers and could itself introduce vulnerabilities. Do not set it.
  • Expect-CT — obsolete; certificate transparency is now enforced by default.
  • Public-Key-Pins — deprecated and dangerous. It could permanently lock users out of your site.

What our audit reports about this

Every item below is measured directly, not inferred. Run it against your own site and the result names the exact rule or header responsible.

  • Each of the six headers, present or missing, with the specific attack each one prevents.
  • Whether CSP is present, and whether it contains directives that undermine it such as unsafe-eval.
  • Whether HSTS has a sufficient max-age and covers subdomains.
  • Whether deprecated headers are still being sent.

For agents and scripts, the same measurement is at /api/v1/security?url=yoursite.com — see the API documentation.

Related questions

Will these break my site?

Five of the six are safe to add immediately. CSP is the exception and genuinely can break things — deploy it in report-only mode first. That is not a formality; it is how you discover the third-party script nobody remembered.

Where do I set them?

At the web server or CDN if you can, since that covers everything you serve including static files. Application-level headers only cover responses your application generates, which is usually a subset.

Does my host set any by default?

Some do, some do not, and some set a subset. Check with curl -sI rather than assuming — this is measurable in seconds.

Read next

All 50 guides · How every check works · API for agents