What headers to add
Here are some of the recommended headers you should consider adding.
With CSP you are in control of what is executed your pages. Ranging from scripts, css, images and their origins/sources.
Or HSTS. This informs browsers that your site should only be accessed using HTTPS. This is important even for a fully static site as it can prevent your page being defaced by anyone able to perform a man in the middle attack.
Cross-site scripting protection. An older header that is replaced by the CSP header, still it can be useful to protect those on older browsers.
Controls if your site can be included in an iframe. It can prevent click-jacking, ie tricking your users into clicking on scams or other malicious code pretending to be from you.
Prevents mime type sniffing and can prevent the execution of normally non-executable content types like images.
Controls the amount of referrer information is sent with navigations (on and offsite). Thus protecting your visitor’s privacy.
A newer header that controls the features (like camera usage) your website can request.
What settings to choose
Lets look closer at the recommended settings and see how we can configure them.
I’ll admit this probably the most tedious one to setup and maintain. I’ve often added a feature and missed the CSP header, wondering why something didn’t work. Usually the dev tools in a modern browser will help you. To be the most secure, be sure to be very specific in what you allow. So while a
default-src * might be tempting, it is as insecure as not having the header at all.
Some examples would be to set it up like this:
default-src 'self' upgrade-insecure-requests if all you have is self-hosted
default-src 'self'; script-src 'self' https://external.script.source; upgrade-insecure-requests to allow loading scripts from some external.script.source.
default-src 'self'; style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; upgrade-insecure-requests to allow for google fonts to load with CSP
MSD web docs has a long list of available options for you to setup.
Not much to this one, it is recommended to set it to a year, so
max-age=31536000 should have you covered. If you want to include all your subdomains automatically.
More info on how it protects you can be found on the qualys blog.
Again not much to this one, just turn it on and make sure it blocks it detects
1; mode=block. It is only for older browsers.
I have this one set to
SAMEORIGIN so I can embed it myself if I wanted to. However it is very unlikely so
DENY is probably the better default.
Just set it to
nosniff and it should prevent your browser from trying to dynamically determine the mime type and avoiding some code execution vulnerabilities. More background on that in this MSD topic.
The default is probably what you’re looking for
strict-origin-when-cross-origin if you don’t use it on your own site either you can limit it even further. I tend to go for
strict-origin myself, rarely need the path or more anyway.
This is a newer one and could take some time to configure if you’re building an app. I’ve just restricted all features. You can play around with this generator to see whats possible. It allows you to control whether your pages can use some of the new apis like cameras, geolocation, battery, etc.
Where to set them
Now that we figured out how to configure everything we need to find out where we can set those headers so they’re actually useful. This can be somewhat of a journey depending on how you’re hosting your static site. Any webserver will have extensive documentation on how your headers can be configured, however some of the free/cheap hosting solutions may have more obscure method to configure these.
For a long time you had to add a worker to your sites to have cloudflare server the security headers. However recently they added it as a featuer on their pages. Simply add a
_headers file (yes thats the exact filename) at the root of your site and cloudflare will do the heavy lifting. You can find the documentation here
GCP allows you to add headers through their load balancers, this may however cost quite a bit extra depending on your setup.
Similar to cloudflare (or the other way around ;)) Netlify offers the ability to specify custom headers in a
_headers file at the root of your site. See their docs for more info.
Meta tags as alternative
If you happen to be stuck some of the headers mentioned above can also be added to your meta tags in a html page. While not quite as effective, it might be better than not having them. Keep in mind that not all features or headers are supported in this way. So if you do have the ability to specify them as headers that is recommended.
Here is an example:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'"> <meta name=”referrer” content=”strict-origin-when-cross-origin” />