Security Headers for the Blog

content security header evaluation

The Internet is a dangerous place, lots of bots have nothing better to do than probe for weaknesses everywhere. As you might know, I use WordPress to run this blog and they are pretty quick to fix security issues when they come up. But since I’m quite a bit on the security conscious side, I decided to add an extra layer of armor with HTTP Security Headers for extra protection for me and of course, you, the reader.

One of the reasons for migrating from Typepad to WordPress was that I could finally serve this blog over https with an SSL certificate. At first I bought one year certificates but have since moved to Letsencrypt. This is all nice and well but a man-in-the-middle attack could downgrade the encrypted https connection to unencrypted http. Well, this is no longer possible as I now set the HTTP Strict Transport Security (HSTS) which instructs the browser to only request future pages on my site via https. In other words, http is permanently switched off!

Other threats that occasionally pop-up are cross-site-scripting and click-jacking attacks. These are based on exploiting bugs that allow inserting Java Script code into the site that communicates with other servers and by putting this website into a frame on another web site and overlay it with invisible ‘buttons’. To counter such attacks I’ve set the following HTTP headers that instruct the browser to only load Java Script and other things from this site and not from anywhere else and to reject any attempts to embed this site into frames of other sites. This way, it can be ensured that all active scripts running on the site can only communicate back to the site and nowhere else:

// Load content including Java Script only locally
 default-src 'self' data:
 font-src 'self' data:
 object-src 'none'
 script-src 'self' 'unsafe-inline' 'unsafe-eval'; " .
 style-src 'self' 'unsafe-inline'; " .
 connect-src 'self'
 worker-src 'self'
 frame-src 'self'

// The website must not be put into a frame. 
// Protects against some forms of click-jacking.
X-Frame-Options: deny

// Block rendering of the complete page if an XSS 
// attack is detected. Note: It would be better to 
// have script-src above not as "unsafe-inline" but 
// since in-line Javascript code is used, it's 
// better than nothing to have this protection.
X-Xss-Protection: 1; mode=block

// The browser must not try to change the MIME header 
// by sniffing. This reduces the risk of running code 
// embedded in up/downloaded files.
X-Content-Type-Options: nosniff

// Always send the full referrer to this page unless 
// there is a downgrade from https to http 
// (which HSTS prevents)
Referrer-Policy: no-referrer-when-downgrade

For more details on the security headers have a look at Scott Helme’s blog post here. If you are running Firefox and want to take a closer look at the headers that are now sent, press F12 on this page which opens the Firefox developer tools and then reload the page. Then go to the ‘network’ tab and have a look at the ‘headers’ of the first ‘GET’ request.

It’s good to see that my efforts seem to have a good effect as gives me a straight A!