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> 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'"
Here is the relevant part of this site’s header:
<link rel="stylesheet" href="https://bghost.xyz/css/style.css" crossorigin="anonymous" integrity="sha512-wGhsiA8zbX/sG1ukda9IYydGYGUN+gJa/Xh/WclbBGR+xh2/+zE9om3PPrwwK5k6AiSBUvOQ81H8KIu70CnkSA=="> <link rel="stylesheet" href="https://bghost.xyz/css/gruvbox.css" crossorigin="anonymous" integrity="sha512-7nVughVX3i4Ry9azGuX8J5MRyy43vcf6T3qSLjn6BO98yB3UmqiQtFkviFv9IdGkm2c+KNyPoo/HsjB+yJ/bSQ==">
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.