GET /April%20King HTTP/2.0

Staff Security Engineer
Mozilla Corporation


Subresource Integrity

When most people think about website security,
they think about this:

What about your seasoned security professional?

A+ on SSL Labs? Time to call it a day!

Content Delivery Networks (CDNs)

Who here has seen code like this?

<script src="">

What does it do?

I'll get into that shortly, but first you must understand...

Same-Origin Policy

Same-Origin Policy

Sites can retrieve and execute code from any origin, but not read its contents.

https:// :443

And once that piece of code is executing, it can read the contents of the same-origin, that is, the scheme, hostname, and port number match.

Same-Origin Policy

<script src="">

When you execute this code, you allow it to:

  • Make XMLHTTPRequests
  • Read all non-HttpOnly cookies
  • Record every keystroke and form entry
  • Abuse permissions to the camera, location, etc.
  • And so much more! 😀

It could simply deface your fine website.

Same-Origin Policy

Or it could do something like @kkotowicz's XSS-Track...

... and create a full-page iframe of your site's login page, easily stealing a user's credentials upon entry.

So what's the big deal?

After all, you're obviously not loading code from Eve & Mallory's Discount JavaScript Emporium!

This is jQuery!

It's the #1 most trusted name in, err… jQuery-ing.


And it's not just a jQuery problem…

GitHub DDoS

If it's such a problem, why does anyone use this?

<script src="">

  • High performance, geolocated servers
  • Smaller requests (no cookies, etc.)
  • Already in the browser cache

All of the A+ scores in the world won't help you if you load a script from a compromised source

So how can one protect themselves against a compromised CDN?

Subresource Integrity
to the rescue!

Subresource Integrity

SRI is a W3C standard that protects from remote resources being tampered with.

What does it look like?

First, generate a message digest (hash) of the known-good file in question:

$ openssl dgst -sha256 -binary jquery-3.1.1.min.js | openssl base64

Because of how cryptographic hash functions work, only this exact file could produce this would produce this hash. Even the slightest modification would result in a completely different hash.

Then, simply update your tags like so:

<script src=""

Note: SRI also works with <link> tags!

So easy, it's practically magic!

💥 ✨ ✨ 🐰


The integrity attribute tells the browser to not load the resource if it doesn't match the correct hash.


And the crossorigin attribute tells your browser to access the resource anonymously, that is, without cookies.

SRI supports the use of multiple hash functions:

  • Your browser picks a hash to use based on what it considers to be the strongest hash function
  • If a hash function becomes broken, your page will still safely load by using an alternative (SHA-3?)

SRI also supports multiple valid hashes
for the same hash function:

  • CDN serves up different library versions based on browser sniffing
  • An upcoming release will replace the existing file, resulting in a different hash



  window.jQuery || (function() {

    var lib = document.createElement('script');

    lib.src = '/assets/js/jquery-3.1.1.min.js';




Simply detect to see if the library has loaded. If it hasn't, then load a locally hosted version.

You can also bind to the tag's onError() event handler.

Use with CSP

Content Security Policy (CSP) is a header that servers can send that defines what sources your browser is allowed to load.

The require-sri-for directive can force browsers to require SRI for any scripts and/or styles that a page loads.

Content-Security-Policy: require-sri-for script style


Didn't you say earlier that you can execute code on foreign origins, but not read it? So how can you compute the hash if you can't read the content?

Drats! I would have gotten away with it, if it wasn't for you meddling security professionals!

Imagine a wifi router on a foreign origin
that returns the following page to a logged-in user:

  "user": "admin",
  "password": "pass1234"

In such a case, an XSS attack could calculate the hashes for thousands of passwords, set the integrity attribute, and keep trying to load the resource until it succeeded.

Luckily for us, there's a solution to this conundrum/quagmire/disaster/apocalypse.

Access-Control-Allow-Origin: *

Access-Control-Allow-Origin (ACAO) is part of the cross-origin resource sharing (CORS) standard.

Servers can set this header, opting in to allow foreign origins to read the contents of their pages.

CDNs host public content, so there is no risk in allowing foreign origins to read their contents.

If the server doesn't set the ACAO header,
the integrity check will automatically fail.

🎉 Good news: most CDNs are already setting this header! 🎉

Is SRI intended for HTTP or HTTPS sites?

Origin Resource Notes
HTTP HTTP Prevents MitM/CDN on foreign request
HTTP HTTPS Prevents MitM/CDN on foreign request
HTTPS HTTP Blocked due to mixed content

SRI Support

as of November 2016

  • Browsers: Firefox 43, Chrome 45/46, Opera 32
  • CDNs: Google APIs, Bootstrap, jQuery, etc.
  • Toolchains: node.js, Sprockets (Rails), etc. can take any URL and generate the proper script tags for you!

Future of SRI

  • Support for other types of resources?
  • Error reporting
  • Support for other cryptographic hash functions?

Feedback on SRI