Sep 08, 2018

Why does subresource integrity (SRI) need the crossorigin attribute?

Subresource Integrity (SRI) is a new security feature that safeguards websites against tampering of a script/stylesheet at the source. Say, you want to include a script from a public CDN, but you also protect yourself against potential manipulation of the code after you have included it, SRI is the way to go. The feature gives the developer the ability to add a hash-sum with the script tag. Before the browser loads the resource, it will match the hash-sum of the content with what is specified in the tag. If they are equivalent browser proceeds with execution, otherwise it’s blocked.

SRI Tag Example:

<script src="https://example.com/example-framework.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8Kuxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

Besides the hash (specified with “integrity”), you also need the “crossorigin” attribute. The browser would refuse to load the script if it’s absent.

"Chrome SRI Error"

Why is the “crossorigin” attribute mandatory?

Short answer: security against cross origin policy violations

First, let’s understand what the attribute achieves. Crossorigin specifies how the browser should handle credentials (Cookies, HTTP Auth Info). It can have two values:

Example: Let’s say a script (https://example.com/abc.js) is being loaded on example-test.com via an SRI tag.

<script src="https://example.com/abc.js"
        integrity="sha384-..."
        crossorigin="anonymous"></script>

If crossorigin is set to “anonymous,” the browser will not send the cookies of example.com in the request header.

If it’s set to “use-credentials,” they will be sent, but only if the response headers of example.com, includes the access control header to whitelist example-test.com. Like: Access-Control-Allow-Origin: http://example-test.com. (More on CORS)

Note: Wildcard (*) in access control header is not allowed in this case.


The SRI spec explains the rationale behind the “crossorigin” attribute:

If that requirement were omitted, attackers could violate the same-origin policy and determine whether a cross-origin resource has certain content.

Attackers would attempt to load the resource with a known digest, and watch for load failures. If the load fails, the attacker could surmise that the response didn’t match the hash and thereby gain some insight into its contents. This might reveal, for instance, whether or not a user is logged into a particular service.

W3 SRI Specification

Example: Let’s say, https://facebook.com/xhr/login returns {status: true} if the user is logged in.

With the attribute absent, the SRI hash could be exploited to reveal that information. E.g., if the user visits example-test.com having a script tag on that page with the integrity hash-sum of {status: true}:

<script src="https://facebook.com/xhr/login"
        integrity="sha384-NmNN5X1LBy0ivZ+fJSALbHxo6hUaAT26+AsI2meLgS3x0IelsjT6asCIBN4oS7sV">
</script>

The default mode of the browser is to send credentials with the resource, which makes the attack trivial. If the script loaded successfully, then that means the user is logged in—information revealed by just a page visit.

The “crossorigin” attribute circumvents this problem by asking the developers to explicitly specify the credentials-sending behavior. It has been made necessary because browser’s default mode would have had disastrous implications.


Follow Me!

I write about things that I find interesting. If you're modestly geeky, chances are you'll find them too.

Subscribe to this blog via RSS Feed.

Don't have an RSS reader? Use Blogtrottr to get an email notification when I publish a new post.