What HSTS and CSP actually do (and why every site should have both)
Two response headers that stop entire classes of attack. If a site doesn't send them in 2026, its operators either don't know or don't care.
Modern browsers are miracle machines. They render arbitrary code from strangers, keep it isolated from your operating system, and only occasionally set your CPU on fire. Two response headers do a disproportionate amount of the work: HSTS locks users to HTTPS, and CSP shrinks the damage any single script can do. Both are one-line additions. Neither costs money. There is no excuse for missing either.
HSTS: HTTP Strict Transport Security
When you type 'example.com' into a browser, the first request goes over plain HTTP unless the site tells the browser otherwise. On a hostile network — an airport, a hotel, a compromised router — that first request can be intercepted, and everything that follows is compromised.
HSTS is a header that tells the browser: for the next N seconds, only ever reach this site over HTTPS. Even if the user types http:// explicitly, even if a link points to http://, the browser upgrades automatically. Once set, downgrade attacks are impossible.
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload- max-age=63072000 — two years, the recommended baseline.
- includeSubDomains — every subdomain is HTTPS-only too. Only turn this on when you're sure.
- preload — request inclusion in Chrome/Firefox/Safari's built-in HSTS list, so the first request is also protected. Requires a manual submission to hstspreload.org.
CSP: Content Security Policy
Cross-site scripting (XSS) has been the top web vulnerability for two decades. When it succeeds, an attacker's JavaScript runs in the victim's browser with the same authority as the site's own code — it can read cookies, exfiltrate form data, or hijack the session.
CSP tells the browser exactly which scripts, styles, images, and other resources are allowed to load. Anything else is blocked. Even if attackers inject a malicious <script> tag through an XSS bug, the browser refuses to execute it.
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.example.com; frame-ancestors 'none'The directives that matter most
- default-src 'self' — everything defaults to same-origin. Everything else is an explicit allow-list.
- script-src — every JavaScript source. Avoid 'unsafe-inline' and 'unsafe-eval' if you possibly can.
- frame-ancestors 'none' — nobody can iframe your site. This obsoletes X-Frame-Options.
- connect-src — where fetch()/XHR can go. Stops exfiltration to attacker-controlled servers.
How to roll CSP out safely
A CSP that blocks something legitimate breaks your site. Start with Content-Security-Policy-Report-Only, which reports violations but doesn't enforce. Collect reports for a week, fix everything that isn't intentional, then flip to the enforcing header.