Using Subresource Integrity (SRI) with Public CDNs

Public CDNs like CloudFlare's cdnjs, Microsoft Ajax Content Delivery Network, Google Hosted Libraries and jsDelivr are awesome. It does not make sense to host public libraries yourself for various reasons, mainly because it is expensive. Using Public CDNs also gives you the advantage that if the browser has seen that script from someone else's site it may be cached already.

The Problem with Public CDNs

Public CDNs, though, do have a downside. As soon as you include a script from a third-party source, it means that they are in control of a script that runs on your site. This means that they can change the content and read cookies among other stuff.

Yes, these Public CDNs are very reliable but they still may be compromised. This is not just a speculative scenario; in 2013, BootstrapCDN began sending files from another hacked web server with a malicious javascript payload.

Subresource Integrity (SRI) to the rescue

Subresource Integrity or SRI is a W3C recommendation to provide a method to protect website delivery. Specifically, it validates assets served by a third party, such as a content delivery network (CDN). This ensures these assets have not been compromised for hostile purposes.

To use SRI, all you need to do is specify a base64-encoded cryptographic hash of the resource you are including in your page in the value of the integrity attribute of any <script> or <link> element.

An integrity value begins with at least one string, with each string including a prefix indicating a particular hash algorithm, followed by a dash, and ending with the actual base64-encoded hash. A resource will be loaded if it matches one of those hashes.

<script src="https://code.jquery.com/jquery-1.11.3.min.js" integrity="sha384-+54fLHoW8AHu3nHtUxs9fW2XKOZ2ZwKHB5olRtKSDTKJIb1Na1EceFZMS8E72mzW" crossorigin="anonymous"></script>  

If the source doesn't match its associated integrity value, then the browser refuses to execute the script or apply the stylesheet, instead returns a network error:

Block Content

Browser Support

According to caniuse.com, at the time of writing this is only supported in Firefox, Chrome and Opera:

Browser Support

Generating the SRI Hashes

You can generate SRI hashes from using openssl:

cat jquery-1.11.3.min.js | openssl dgst -sha384 -binary | openssl enc -base64 -A  

Additionally, the SRI Hash Generator at https://srihash.org/ is an online tool you can use to generate SRI hashes.

Fallback

If the source doesn't match its associated integrity value, then the browser refuses to execute the script or apply the stylesheet. This will, most probably, leave your page in a non-working state.

You need to have a fallback plan. Ideally, you host a copy of the script on your own servers. To recover from a failure, you could then check at runtime if the library is loaded. If not, you need to load it from your own domain (where you know it is integral since you are hosting it):

<script>window.jQuery || /* reload from own domain here */;</script>  

Conveniently, this is also a good idea to have just in case the CDN is down!