This website is now slightly more secure, since I recently added Strict Transport Security headers to the http response. Modifying the headers used to be a difficult and convoluted process to achieve on AWS using Lambda@Edge, but now with new ✨ cloudfront functions ✨ it’s much simpler.

The relevant code snippet is here, courtesy of Serhii Vasylenko:

function handler(event) {
var response = event.response;
var headers = response.headers;

headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains'}; 
headers['x-content-type-options'] = { value: 'nosniff'};
headers['x-xss-protection'] = {value: '1; mode=block'};
headers['referrer-policy'] = {value: 'same-origin'};
headers['x-frame-options'] = {value: 'DENY'};

return response;

When you send an http request to the site, HSTS means you get a response saying it’s https only. The main effect (as I understand it) is to protect against a specific vulnerability which arises in that first connection. If you just type the bare domain ie. ‘’ without specifying https, the browser checks the unencrypted http connection first, and is then redirected to https. That first unencrypted connection is a danger and you can avoid it by strictly requiring https only. It also protects against the degrading of the connection with less-secure resources.

If a site has Strict Transport Security headers with ‘preload’ specified, you can submit it here, and it’ll get picked up in lists included in the main browsers. If the browser sees your site on its list, it already knows your site is https only and it won’t even check http.

I assume as most of the internet adopts https, browsers will eventually just stop using unencrypted connections by default.

I submitted my site to the preload list on 29th June, and at time of writing it hasn’t turned up in commits to the Chromium repository. It might make it into the next version of Chrome?

⚠️ Warning: if you do this, you should treat it like a permanent change. It takes a few months to get https preloaded in the browser, it also takes a few months to reverse it. If you really do want to go for it, simply add ‘preload’ to the http response header. ⚠️


There is a small performance benefit to preloading https. Lighthouse shows the redirect path when typing the bare domain into the browser:

URL time
http:// 630 ms
https:// 480 ms
https://www. done!

Eliminate that first redirect and speed up the page load by up to 630ms! If you’re not already pushing the limits of web page performance, this is like a free speed boost.

If you’re worried about unencrypted connections on other websites, download the https everywhere extension from the Electronic Frontier Foundation. I’ll highlight that this is particularly useful if you’re visiting Chinese websites, as these often only begrudgingly support https. The People’s Republic seems generally opposed to encrypted web connections, the failure to adopt TLS is so widespread that it has to be an intentional policy. If you’re connecting to the Chinese web, check your security.

Content Security Policy

Along with HSTS you can set a Content Security Policy in the http header. These things all sort of go together as part of the typical collection of security headers.
The Content Security Policy tells the browser mainly where to accept resources from, and it’s mainly useful for preventing cross-site scripting. The code I copied from Vasylenko blocked inline CSS and immediately broke the site layout in a variety of unhelpful ways. So, there’s an exception for unsafe-inline styling, and the main site CSS is secured with subresource integrity.

I don’t think this site is a security risk, blocking various external resources in the Security Policy is not a problem because everything here is already very self-contained to begin with. The only thing it has properly broken is embedded maps, I need to a way to whitelist OpenStreetMap tiles.

I haven’t added a permissions policy yet. It’s safe to say this site will never request access to your camera, or take payments.

EDIT: As of November 2021, response headers can be set in the cloudfront dashboard, you no longer need functions to achieve this!