HSTS and http headers redux

This site is now included in in the HSTS preload list, and will not be served over an unsecure connection. In an effort to continually employ best security practices, I have successfully removed the unsafe-inline from the site’s Content Security Policy. I did this by changing way I am using Hugo’s syntax highlighting in the config.toml file. By enabling pygmentsUseClasses, I was able to use CSS to style code blocks as opposed to having the styles in a bunch of ugly <span></span> tags generated by pygments.

pygmentsCodeFencesGuessSyntax = true
pygmentsCodeFences = true
pygmentsUseClasses = true

Now my Content Security Policy does not allow for inline styling, meaning all resources are served securely from domains explicitly specified in the page header and footer. This is used to define where various web resources can be loaded from and can also be used to mitigate cross-site scripting (XSS) attacks. Below is the Content Security Policy for this site:

# explicitly stipulate what content can be loaded and from where
# "require-sri-for" allows only styles and scripts that match a cryptographic hash to be loaded
Header always set Content-Security-Policy "default-src 'none'"; \
    "font-src 'self' https://fonts.gstatic.com"; \
    "img-src https: 'self'; object-src 'none'; script-src 'self'"; \
    "style-src 'self' https://fonts.googleapis.com"; \
    "require-sri-for style script; frame-ancestors 'none'"

The above Content Security Policy (CSP) uses best security practices limiting what can be loaded and where it can be loaded from to this domain and a couple of specific Google Fonts. It no longer allows for ‘unsafe-inline’ in the style-src directive. Additionally, the CSP requires that all javascript originates from this domain, as well as invoking the upcoming standard of requiring Subresource Integrity for scripts and stylesheets, which once supported by various browsers, will mean that browsers will refuse to load stylesheets and scripts without a valid integrity attibute (a cryptographic hash of the script’s content) throughout this site. Here is an example piece of code from this site’s source, which lazily loads some webfonts from Google:

<script src="/js/loadFont.js"

Here is the relevant part of this site’s header:

<link rel="stylesheet" href="https://bghost.xyz/css/style.css"
<link rel="stylesheet" href="https://bghost.xyz/css/gruvbox.css"

When the script is invoked with the above Content Security Policy in a supported environment, the browser will check the content of the script against the value of the hash, in this case using sha512. If the hash of the script file or stylesheet is not equal to the hash specified in the integrity property, the browser will fail to load the script, therefore preventing a malicious script from being loaded in place of the intended one, or a stylesheet from changing the look of the site. This is specifically useful for resources hosted on other people’s networks, the most common example being CDNs such as Cloudflare or Akamai.

The downside of this, of course, is an increased maintenance burden. Every time any of the stylesheets or scripts are altered or updated, a new hash must be computed and placed in the proper template files. It is possible to generate a hash using OpenSSL, or LibreSSL with the following command:

cat $stylesheet | openssl dgst -sha512 -binary | openssl enc -base64 -A

Of course, this can always be piped to a file or put into a script.

As always, please contact me with any errors or ommissions, and I will do my best to fix or clarify things.