A+ Security and Subresource Integrity

Mozilla Observatory Scan Summary for moshteitelbaum.com

Security is hard; there’s no getting around that fact. As smart as the Good Guys may be, the Bad Guys tend to be just as smart and both sides are in an endless fight to overcome the other side’s latest improvement. Add in the fact that public web applications are on the Internet where anybody can access them and interact with them in potentially unpredictable ways and securing them can be an absolute nightmare.

Fortunately, there are a number of really great services available that can take a look at some of the steps you’ve taken to secure your application and let you know what you’ve done well and what needs improvement. My personal favorite of these services is Mozilla Observatory. It puts your site through 11 different tests, grades you on your effort, and provides links to information about what the tests cover and what you can do to improve your results. It also links to third-party tests so you can continue down the security rabbit hole. With the help of Observatory, I was able to relatively quickly secure this site and earn an A+ score.

When I first started writing this blog post, I had intended to go over each of the 11 tests, what they were checking for, and how you could make sure your site was secured appropriately to pass each of them. But partway through I realized that I was just re-explaining what Mozilla already explains very well so instead, I’ll just point you to their Web Security Guidelines and leave it at that.

However, I do want to go a bit deeper into the one test that this site did not pass, the Subresource Integrity test. Modern web apps are made of lots of different parts. This includes HTML, CSS, images, JavaScript, and more. And, if you’re using any third party services (this site uses Google Fonts, Google Analytics, Google reCAPTCHA, Bootstrap, and Bootstrap Icons), like most modern apps do, that adds to the list.

Subresource Integrity speaks to these third-party resources. When you include code from third-parties, you are trusting them to be safe and dependent upon their owners to keep them secure. As much as you might secure your own site, if a Bad Actor manages to gain control of the third-party resource, they can now attack your site. Subresource Integrity is a standard that allows you to prevent the execution of the third-party code if it gets changed without your knowledge.

Let’s look at 3 examples of how this site includes external scripts:

The first <script> tag, in addition to the src attribute which specifies the location of the script, includes integrity and crossorigin attributes which are how Subresource Integrity is enabled. The integrity attribute specifies a cryptographic hash of the contents of the script as of the time it was added to your site. If the contents of the script are updated, the hash will be different and the browser will not execute the script. The crossorigin attribute should always be set to “anonymous” to instruct the browser to send requests for the script without cookies.

Let’s skip to the third <script> tag which specifies a locally-stored script. You could generate an SRI Hash for these but, if a Bad Actor manages to gain access to your code such that they could modify the contents of a local script, they’d also be able to update the referring code with a new hash so there’s no real point here.

The second <script> tag is an example of why this site did not pass the SRI test. This tag, and all of the others that point to a Google-provided service, do not include SRI attributes. If you look back at the <src> attribute of the first <script> tag, you’ll notice that it includes version information. Bootstrap and many other providers of online services do this specifically so that, if they update their code, they can make it available under a different version number at a different URL, and they won’t accidentally break any SRI-enabled references to it now that the hash will have been changed.

Google, I’m assuming because they update their code so often (?), don’t use this sort of versioning specification in the URL. This results in not being able to include SRI details because, if you did, as soon as they update the code at the URL you reference, the hash will change and browsers will stop executing that code, potentially breaking use of your site. This puts you, the developer and/or site owner in the position of having to choose between enhanced security vs. functionality. For this site, largely because Google is the company that it is, I’ve decided to continue using their services without the benefit of SRI.

When using a third-party service on your own site, make sure you weigh the pros and cons, taking into account not just who the maintainer is but also where the resource is located. Going back to the Bootstrap script above, as much as I may trust the Bootstrap team, the code is located on a CDN over which they have no control. If SRI wasn’t available here, I would have gone the route of using a local copy instead.

So there you have it; while not all easy, it doesn’t take a ton of work to significantly improve the security of your site and the safety of those who visit it. Go get your A+!

2021-02-05 14:03:49