Packet To Sniff
Web securityBeginner

HTTP security headers explained: CSP, HSTS and more

Security headers tell browsers how to protect your users. Learn what CSP, HSTS, X-Content-Type-Options, Referrer-Policy, Permissions-Policy and frame-ancestors do.

By Packet To SniffPublished 3 min read

Helpful background: TCP vs UDP: differences, handshakes and when each is used.

On this page

When a browser loads a page, the server sends headers before the HTML. A handful of them turn on protections that are built into every modern browser but are off, or loose, by default. They cost almost nothing to add and block whole classes of attack.

How to see a site's headers

Bash
curl -sI https://example.com

-I asks for headers only; -s hides the progress bar. Paste the output into the security headers analyzer to check it. The analyzer only reads what you paste; it does not contact any site.

The headers that matter

Strict-Transport-Security (HSTS)

HTTP
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Tells the browser: for the next max-age seconds (here two years), only ever connect to this site over HTTPS, even if the user types http://. This defeats SSL-stripping attacks on hostile networks.

  • Only send it over HTTPS, and only once HTTPS works everywhere on the domain.
  • includeSubDomains covers every subdomain, so be sure they all support HTTPS.
  • preload is a request to be added to browsers' built-in HSTS list. Removal takes time, so add it deliberately.

Content-Security-Policy (CSP)

HTTP
Content-Security-Policy: default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'

CSP is an allowlist of where the page may load scripts, styles, images, frames and connections from. If an attacker injects <script src="https://evil.example/x.js">, a CSP without that origin blocks it.

  • The strongest policies use nonces or hashes for scripts instead of allowing 'unsafe-inline'.
  • Roll out with Content-Security-Policy-Report-Only first, fix what breaks, then enforce.
  • A policy containing 'unsafe-inline' for scripts still helps (it limits external sources, framing, plugins and more) but gives much weaker protection against injected inline scripts.

X-Content-Type-Options

HTTP
X-Content-Type-Options: nosniff

Stops browsers from guessing a file's type. Without it, a file uploaded as .txt could be sniffed and executed as script or rendered as HTML.

Frame protection (clickjacking)

HTTP
Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY

Clickjacking loads your site invisibly inside an attacker's page and tricks users into clicking. frame-ancestors in CSP is the modern control; X-Frame-Options is the older header still sent for compatibility. Use 'self' or SAMEORIGIN if your own site needs to frame its pages.

Referrer-Policy

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

Controls how much of the current URL is sent to other sites when a user clicks a link. Full URLs can contain search terms, tokens or IDs. strict-origin-when-cross-origin sends only the origin to other sites and nothing when going from HTTPS to HTTP. Modern browsers use it as the default, but sending it explicitly documents your intent.

Permissions-Policy

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

Turns off powerful browser features your site does not use, so injected code or embedded frames cannot request them.

Headers you can drop

  • X-XSS-Protection: controlled an XSS filter that browsers have removed. Omit it or send 0.
  • Server and X-Powered-By: not security controls; they advertise your software and version. Removing them does not fix vulnerabilities but gives attackers less free information.

A sensible starting set

Header Starting value
Strict-Transport-Security max-age=31536000; includeSubDomains
Content-Security-Policy Start from default-src 'self', then allow what you actually use
X-Content-Type-Options nosniff
Referrer-Policy strict-origin-when-cross-origin
Permissions-Policy Disable features you do not use
X-Frame-Options DENY (plus frame-ancestors in CSP)

Summary

  • A few response headers switch on strong browser protections.
  • HSTS forces HTTPS; CSP limits where content loads from; nosniff, frame protection, Referrer-Policy and Permissions-Policy close smaller gaps.
  • Headers add defence in depth; they do not replace fixing the underlying bugs.

Frequently asked questions

Should I still send the X-XSS-Protection header?

No. Modern browsers have removed the XSS auditor that this header controlled. Current guidance is to omit it or set it to 0, and to rely on a Content-Security-Policy and correct output encoding instead.

Can security headers fix an XSS vulnerability?

No. A strict Content-Security-Policy can make many XSS bugs much harder to exploit, but the fix is still to encode output correctly and avoid unsafe HTML. Headers are a second layer, not a replacement.

How do I see a site's response headers?

Run curl -sI followed by the URL in a terminal, or open the browser developer tools, go to the Network tab, select the page request and look at the response headers.

Continue learning

Tags