Subresource Integrity

This article has been superseded by a more-recent write-up of my presentation from OWASP AppSec EU 2015. Alternatively, you can download the slides or watch the video on YouTube

Some time ago, I complained about the prevalence of CDNs for JavaScript hosting and the trust model that comes with including JS files into your web page: Every script may read and request towards everything that is on your this website and all your other websites. This is because of the Same-Origin Policy.

After that, Brad Hill (co-chair of the W3C Web Application Security Working Group) asked me to help co-edit1 one of the deliverables for the working group: A possible feature for the web platform to ensure that resources embedded or included in a document (e.g. script files from other origins) have not been tampered with and are indeed the ones the content author intended to use. This upcoming specification is called Subresource Integrity (SRI)2 .

The idea is that we include a third party script along side a cryptographic hash of its content. The web browser may then compute the hash on retrieving the file and compare if it's the one it expected to receive. This is how this would look in mark-up:

<script src="https://analytics-r-us.com/track.js"
        integrity="ni:///sha-256;SDfwewFAE...wefjijfE?ct=application/javascript"></script>

While certainly not aesthetically appealing, we are using this ni:// notation because it is already defined in RFC 6920. This mostly saves us time explaining things in the spec and might allow implementations to re-use existing code. The first half of the ni:// URL explains which hashing function to use (i.e., SHA-256) while the second part contains the base64url encoded4 digest that SHA-256 produces on the content of the script. The ct bit says explicitly what kind of content we should expect. This defends against content type spoofing attacks.

Does this mean a script update breaks my web page?

Your website does not have to break when the script file changes. The previous example given does indeed block a script once the file changes. And this may make your website unusable. But you can also provide a fallback mechanism: you simply say that the script should be loaded from a CDN that is fast and likely cached within the browser. But it must match the hash. If this is non canonical location does not work, the browser can still load the file from your own domain - albeit a little slower:

<script src="http://example.com/script.js"
        noncanonical-src="http://cdn.example.com/script.js"
        integrity="ni:///sha-256;jsdfhiuwergn...vaaetgoifq?ct=application/javascript"></script>

See how we changed the attributes? Now src points to the file that you host yourself. And the CDN is mentioned as a non canonical source. This will make the website work for every case. But you still get the speed bonus from the CDN.

Content addressable storage: More than a CSP Bypass?

A useful feature that piggy-backs on SRI might be content-addressable storage: The idea is, once you can identify a resource by its hash, you could save yourself the trouble and asking the server for it, if it's already cached from some other domain.

The problem that comes with this idea is cache poisoning: The client still has to find out if the server really hosts this file. Otherwise an attacker could trick your browser into believing that you host files which you don't. Content injection (XSS) may then use a previously stored hash so that it looks like you are hosting the evil JavaScript payload that the browser has previously seen on evil.com. This nifty attack was raised by Michal Zalewski on the webappsec w3c mailing list. My co-worker Mark Goodwin suggests that we may allow this for hashed files that are already allowed through hashes in CSP 2 script-src hashes.

The foul fruit called integrity-checked active mixed content

Another idea that has been raised on the mailing list was mixed content: Modern browsers currently block active mixed content, i.e., plain-HTTP scripts on HTTPS websites. Somebody suggested we might disable this blocking if SRI is used to make sure that the resource has not been tampered with. While this is a reasonable argument for the functionality of the script, it leaves out the confidentiality aspects: HTTPS is also about confidentiality, and I contend we should continue blocking active mixed content, even if it contains an SRI integrity attribute.

What I do like is that this suggestion looks at JavaScript as a means to deliver software. And I hope that SRI can play a part in the story of making software (i.e., script) delivery on the web a bit more secure.

SRI helps WebCrypto

The story with WebCrypto could really improve through SRI: Although WebCrypto is considered harmful by Matasano Security, I think SRI could fix some of the things that are wrong with webcrypto: The reality is, more and more applications are implemented as web applications. Firefox OS has taught me that backend-less, JavaScript-only applications can power a full phone operating system. And these systems really need crypto. The question is just how we do it: It is much safer to use something provided by the platform than using pure JavaScript Cryptography3. I also think that a tiny web page may bootstrap an application and verify that trusted code has indeed not been tampered with, by including all subresources with integrity attributes. This tiny web page may even be stored locally as a safe entry point into websites that use WebCrypto.

Site-wide Subresource Integrity with CSP

Subresource Integrity plans to extend CSP to include an integrity-policy directive. This would allow you to apply integrity checks for all resources on your site. And this also means that a failed integrity check will be reported just like CSP violations. You will then be able to enforce and verify integrity for your whole web page.

Implementation Status

Subresource Integrity is not in your browser. Google Chrome has an implementation that works only for scripts and only on secure origins (e.g. HTTPS websites). A similarly reduced implementation for Firefox is currently planned. Those attempts also exclude integrity-policy in CSP and violation reports. In the long run we still want integrity checks for all kinds of subresources (e.g., images, styles, iframes).


  1. The spec is joint work with some brilliant people: Devdatta Akhawe from UC Berkeley and Joel Weinberger and Mike West from Google. 

  2. It is currently in an early state, that is called "First Public Working Draft. And by the way: The worst thing you can do to your inbox is have your email address published on a W3C website. 

  3. Thinking about timing attacks, for example. 

  4. The url-safe Base64 encoding is explained in RFC4648: The Base16, Base32, and Base64 Data Encodings

All posts

  1. Reference Sheet for Principals in Mozilla Code (Mon 03 August 2020)
  2. Hardening Firefox against Injection Attacks – The Technical Details (Tue 07 July 2020)
  3. Understanding Web Security Checks in Firefox (Part 1) (Wed 10 June 2020)
  4. Help Test Firefox's built-in HTML Sanitizer to protect against UXSS bugs (Fri 06 December 2019)
  5. Remote Code Execution in Firefox beyond memory corruptions (Sun 29 September 2019)
  6. XSS in The Digital #ClimateStrike Widget (Mon 23 September 2019)
  7. Chrome switching the XSSAuditor to filter mode re-enables old attack (Fri 10 May 2019)
  8. Challenge Write-up: Subresource Integrity in Service Workers (Sat 25 March 2017)
  9. Finding the SqueezeBox Radio Default SSH Passwort (Fri 02 September 2016)
  10. New CSP directive to make Subresource Integrity mandatory (`require-sri-for`) (Thu 02 June 2016)
  11. Firefox OS apps and beyond (Tue 12 April 2016)
  12. Teacher's Pinboard Write-up (Wed 02 December 2015)
  13. A CDN that can not XSS you: Using Subresource Integrity (Sun 19 July 2015)
  14. The Twitter Gazebo (Sat 18 July 2015)
  15. German Firefox 1.0 ad (OCR) (Sun 09 November 2014)
  16. My thoughts on Tor appliances (Tue 14 October 2014)
  17. Subresource Integrity (Sun 05 October 2014)
  18. Revoke App Permissions on Firefox OS (Sun 24 August 2014)
  19. (Self) XSS at Mozilla's internal Phonebook (Fri 23 May 2014)
  20. Tales of Python's Encoding (Mon 17 March 2014)
  21. On the X-Frame-Options Security Header (Thu 12 December 2013)
  22. html2dom (Tue 24 September 2013)
  23. Security Review: HTML sanitizer in Thunderbird (Mon 22 July 2013)
  24. Week 29 2013 (Sun 21 July 2013)
  25. The First Post (Tue 16 July 2013)