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

Other posts

  1. logging with MOZ_LOG on the try server
  2. Challenge Write-up: Subresource Integrity in Service Workers
  3. Finding the SqueezeBox Radio Default SSH Passwort
  4. New CSP directive to make Subresource Integrity mandatory (`require-sri-for`)
  5. Firefox OS apps and beyond
  6. Teacher's Pinboard Write-up
  7. A CDN that can not XSS you: Using Subresource Integrity
  8. The Twitter Gazebo
  9. German Firefox 1.0 ad (OCR)
  10. My thoughts on Tor appliances
  11. Subresource Integrity
  12. Revoke App Permissions on Firefox OS
  13. (Self) XSS at Mozilla's internal Phonebook
  14. Tales of Python's Encoding
  15. On the X-Frame-Options Security Header
  16. html2dom
  17. Security Review: HTML sanitizer in Thunderbird
  18. Week 29 2013
  19. The First Post