Content Security Policy
Running this site via the excellent Security Headers security tool results in the following report summary:
An A rating is pretty good, putting it within the top 25% receiving that rating. I would rather achieve the A+ rating, putting it within the top 3% 😁
What is missing is a Content-Security-Policy
header, so let us see what can be done.
What is it?
Not being a front-end web engineer I was not immediately familiar with this initiative, so embarked on research into the details. Good starting places are:
- Content Security Policy - An Introduction by Scott Helme, the author of the Security Headers tool
- Content Security Policy (CSP) Quick Reference Guide
To quote Scott’s article:
Content Security Policy is delivered via an HTTP response header, much like HSTS, and defines approved sources of content that the browser may load. It can be an effective countermeasure to Cross Site Scripting (XSS) attacks and is also widely supported and usually easily deployed.
Setting the header
As I am using nginx to serve my static site the answer to this is pretty straightforward. In my custom nginx.conf
I can add an additional header using:
add_header Content-Security-Policy "<policy>";
The big question is what should the <policy>
be?
How to determine the policy?
This site is generated using Hugo, which I imagined would be ‘doing the right thing’. Ergo, I figured a good starting place would be to define the following Content-Security-Policy
:
add_header Content-Security-Policy "default-src 'self'";
Opening the site in Chrome with the developer tools, showed the following errors on the homepage:
The second error is occuring because the following <script>
is not being allowed to execute, due to the CSP:
<script>let haveHeader = false;</script>
As suggested by the error message, I added the hash to the CSP for this particular script:
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'sha256-mzxFK7/AUlIhalqxiKcyRO9mSXWeALlmGjRumxphi9M='";
Refreshing the page fixed these errors 👍🏻. Next, I visited about me and got 3 more errors in the console:
Interestingly, the latter two errors are caused by a very similar script as above. However, this time haveHeader
is being set to true
. Surely enough added the suggested hash to the CSP resolved these.
Unfortunately, adding the suggested hash for the style-src
did not resolve that error. I am unsure why, so I have temporarily gone with the second suggestion of adding unsafe-inline
. Navigating around the rest of the site did not result in any more console errors due to blocked content. This leaves us with an initial Content Security Policy
of:
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'sha256-mzxFK7/AUlIhalqxiKcyRO9mSXWeALlmGjRumxphi9M=' 'sha256-AnD4MU8ryLQfUOxyB+K8iDV82R0rMK6os4wCSP8Cqqo='; style-src 'self' 'unsafe-inline';";
Wrapping up
Having gone through this exercise, let’s re-run the security header check and see what the rating now is:
An A+ rating - excellent… This earns us a spot in the ‘Hall of Fame’, albeit temporarily:
Obviously should the scripts for setting hasHeader
change this CSP will break. In addition, I am not entirely thrilled by having unsafe-inline
for style-src
. Therefore, I will reach out to the author of the theme I am using to find out if there is a better way™
UPDATE: I have raised #22: Content Security Policy on GitHub with Track3, the theme author, in case I am missing some Hugo magic.
UPDATE 2: Track3 updated his theme very quickly, removing the need for any of these workarounds - thanks. The site’s Content-Security-Policy
is now:
add_header Content-Security-Policy "default-src 'self';";