Using Subresource Integrity is rather simple:
The idea is to include the script along with its cryptographic hash (e.g. SHA-384) when creating the web page. The browser can then download the script and compute the hash over the downloaded file. The script will only be executed if both hashes match. The security properties of a collision resistant hash function, ensure that a modification results in a very different hash. This helps the site owner detect and prevent any changes, whether they come from a compromised CDN or an evil administrator.
An important side note is that for Subresource Integrity to work, the CDN must support Cross-Origin Resource Sharing (CORS). The
crossorigin attribute in the above code snippet enforces a CORS-enabled load. The anonymous value means that the browser should omit any cookies or authentication that the user may have associated with the domain. This prevents cross-origin data leaks, and also makes the request smaller.
As you may have noticed, the integrity attribute does not just include the hash value. It also contains the digest name. The syntax for the integrity attribute allows multiple tokens of this name-value format. This allows site owners to specify hashes of different strengths as well as the values of multiple scripts that may be behind a URL. This is useful for browser sniffing or content negotiation.
For the best performance, users would load all resources from the CDN, but if integrity cannot be verified, you don’t want your users to be trapped on a non-working web page. To make failover work, we recommend hosting a copy of the script on your own origin. To recover from failure one could then extend the previous snippet with the following code:
<script>window.jQuery || /* reload from own domain here */;</script>
This code will check if jQuery has been defined and could otherwise insert a script tag that loads the same origin version of the script.
Please note that many scripts update regularly, especially if they do not come with a version number. If you want to secure your CDN-loaded scripts, it is best to stick to a specific version and not use filenames with the word ‘latest’ in them.
HTTP or HTTPS?
Subresource Integrity works on both HTTP and HTTPS. If you are serving your page over plain HTTP, the browser can still figure out if the script was modified on the CDN, but it is not protected against active network attackers, as they would be able to just remove the integrity attribute from your HTML. It is, however, in the interest of your users to provide confidentiality, integrity, and authenticity of your web applications by using HTTPS for the entirety of your website.
While we are working on adding support for subresources other than scripts, you can also use Subresource Integrity for CSS. Just use the integrity attribute that you now know so well on your <link> tag!
Try Subresource Integrity Now!
If you want to test browser support or toy with examples, take a look at https://srihash.org/, which can do all the grunt work of computing hashes as well as checking if your CDN already supports HTTPS. A few early adopters like BootstrapCDN, CloudFlare and GitHub are already experimenting with it.
There is some additional documentation of Subresource Integrity on MDN. But if you want to read all the fine details of Subresource Integrity, take a look at the specification.
To conclude, Subresource Integrity can make your website safer when using a CDN that you do not fully control. It’s as simple as adding just a few extra attributes to your script tags.
About Frederik Braun
Frederik Braun defends Mozilla Firefox as a Staff Security Engineer in Berlin. He's also a member of the W3C Web Application Security Working Group and co-authored the Subresource Integrity standard.
About Francois Marier
Security and Privacy Engineer