Acing your HTTP Security Headers Exam

After you've hardened your site with appropriate TLS, what's next? Correct answer: HTTP security headers!

Security headers let you use built-in security features of modern browsers that are turned off by default, not to break old sites. A lot of these headers exist as much or more to protect your visitors rather than your site itself.

If you want to know the status of your headers, use the excellent scanner on If there actually was a security headers exam for sites, that would be it.  A lot of this blog post also comes from the site of Scott Helme, the maker of - a lot of credit to him.

1. HSTS - HTTP Strict Transport Security

The Strict-Transport-Security header disallows the visitor's browser to connect to your site using plain old HTTP. This could avert man in the middle attacks de-/reencrypting contents in transit.

Protects against: protocol downgrade attacks and cookie hijacking.

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

Read more about HSTS

2. CSP - Content Security Policy

The Content-Security-Policy header lets you whitelist the resources your page can use, and how they can use them. With CSP you control wether your site allows inline JavaScript, which domains scripts, images, iframes, fonts etc. can be loaded from.

Getting your existing site to work with a strict CSP can be a lot of work. The biggest gripe is getting rid of 'unsafe-inline' when using CMS platforms like WordPress or Ghost, or with bothersome third-party add-ons. Currently 'unsafe-inline' is actually active on this site (shh, don't tell anyone) only because Disqus doesn't work without it. One more item on the cons list for Disqus, which I'll be replacing. So currently, Disqus is preventing me from going from A to A+ on

Protects against: cross site scripting (XSS) and script injections.

Sample setting: Content-Security-Policy: script-src 'self' 'unsafe-inline'; object-src

The above allows inline scripts and scripts loaded from a list of named domains.

The good thing about CSP is that you can dry run it using the header Content-Security-Policy-Report-Only. Using that header, your browser will load all content but show warnings in the console about what would be blocked if used the actual CSP header. This is extremely useful since constructing the right CSP header can be very complicated and if you use the live one (without Report-Only) it can be hard to see what doesn't load properly.

Read more about CSP

3. Referrer Policy

Referrer policy controls what information is included when a visitor clicks on a link going out of your site. Why do you want to restrict this information? Well, for one thing if your site isn't public it doesn't make sense to relay your internal URLs to a third party. On this site, I'm fine with that (it might even generate some traffic), so I opted to send referrer info, but only when the target site uses TLS.

Protects against: divulging internal information about your site

Sample setting: Referrer-Policy: no-referrer-when-downgrade

Read more about Referrer Policy

4. Content Type Options

There's only one setting for X-Content-Type-Options: nosniff. That makes the browser always use the content-type you've set for a resource instead of what the browser might think it should be.

Protects against: accidentally treating user-uploaded files as executables

Sample setting: X-Content-Type-Options: nosniff

Read more about Content-Type-Options

5. Frame Options

X-Frame-Options tells the browser where, if anywhere, your site should be allowed in an iframe. For this blog I'm using SAMEORIGIN, since the Ghost editor shows a preview of the site in an iframe.

Protects against: your site being hijacked and shown as a part of other sites.

Sample setting: X-Frame-Options: SAMEORIGIN

Read more about Frame Options

6. XSS Protection

X-Xss-Protection protects against... yes, cross-site scripting. You can set it to 1 to activate it and to 1; mode=block to have it completely block scripts instead of trying to make them safe by sanitation.

Protects against: your visitors getting malicious scripts run using your site

Sample setting: X-Xss-Protection: "1; mode=block"

Read more about XSS Protection

7. Feature Policy

Feature-Policy is the newest member of the HTTP security headers family. It regulates which browser external features a site wants to white-list. Examples of such features are vibrations, camera, microphones and accelerometer.

I didn't actually get around to setting this header on this blog, at least not yet. It's not widely implemented in browsers yet.

Protects against: unintended use of device features, like spying through the camera, using your site.

Sample setting: Feature-Policy: vibrate 'self'; usermedia *; sync-xhr 'self'

Read more about Feature Policy

Additional resources

There's an online validator for your CSP header, which is the trickiest one to get right:

Apart from that, keep running until you get an A.

comments powered by Disqus
Find me on Mastodon