Subresource Integrity (SRI) is a security feature that enables browsers to verify that files they fetch (for example, from a CDN) are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched file must match.
How Subresource Integrity helps
Using Content Delivery Networks (CDNs) to host files such as scripts and stylesheets that are shared among multiple sites can improve site performance and conserve bandwidth. However, using CDNs also comes with a risk, in that if an attacker gains control of a CDN, the attacker can inject arbitrary malicious content into files on the CDN (or replace the files completely) and thus can also potentially attack all sites that fetch files from that CDN.
The Subresource Integrity feature enables you to mitigate some risks of attack such as this, by ensuring that the files your Web application or Web document fetches (from a CDN or anywhere) have been delivered without a third-party having injected any additional content into those files — and without any other changes of any kind at all having been made to those files.
Note: The subresource integrity feature does not mitigate all risks. Third party JavaScript is often designed to depend on tertiary data, including ajax requests that may fetch data stored on the script provider's site, other third parties or even data users enter, like query parameters and input values. These are often needed to support the JavaScript's functionality, as perhaps a map library would need to fetch map <svg> data to render, but that could include onclick attribute events.
Using Subresource Integrity
You use the Subresource Integrity feature by specifying a base64-encoded cryptographic hash of a resource (file) you’re telling the browser to fetch, in the value of the integrity attribute of any <script> or <link> element.
An integrity value begins with at least one string, with each string including a prefix indicating a particular hash algorithm (currently the allowed prefixes are sha256, sha384, and sha512), followed by a dash, and ending with the actual base64-encoded hash.
An integrity value may contain multiple hashes separated by whitespace. A resource will be loaded if it matches one of those hashes.
Example integrity string with base64-encoded sha384 hash:
sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC
An integrity value’s “hash” part is, strictly speaking, a cryptographic digest formed by applying a particular hash function to some input (for example, a script or stylesheet file). But it’s common to use the shorthand hash to mean cryptographic digest, so that’s what’s used in this article.
Tools for generating SRI hashes
You can generate SRI hashes from the command-line with openssl using a command invocation such as this:
cat FILENAME.js | openssl dgst -sha384 -binary | openssl -base64 -A
or with shasum using a command invocation such as this:
shasum -b -a 384 FILENAME.js | xxd -r -p | base64
Additionally, the SRI Hash Generator at https://srihash.org/ is an online tool you can use to generate SRI hashes.
Content Security Policy and Subresource Integrity
You can use Content Security Policy to configure your server to mandate that specific types of files require the use of Subresource Integrity. Do this using the require-sri-for directive in your CSP header. For example:
Content-Security-Policy: require-sri-for script;
This requires that any attempts to load JavaScript will only succeed if the Subresource Integrity information is in place and the integrity check succeeds.
You can also specify that SRI should be used when loading stylesheets:
Content-Security-Policy: require-sri-for style;
You can also specify both script and style to mandate SRI for both kinds of file.
Examples
In the following examples, assume that oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC is already known to be the expected SHA-384 hash (digest) of a particular script example-framework.js, and there’s a copy of the script hosted at https://example.com/example-framework.js.
Subresource Integrity with the script element
You can use the following <script> element to tell a browser that before executing the https://example.com/example-framework.js script, the browser must first compare the script to the expected hash, and verify that there’s a match.
<script src="https://example.com/example-framework.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>
For more details on the purpose of the crossorigin attribute, see CORS settings attributes.
How browsers handle Subresource Integrity
Browsers handle SRI by doing the following:
- When a browser encounters a
<script>or<link>element with an integrity attribute, before executing the script or before applying any stylesheet specified by the<link>element, the browser must first compare the script or stylesheet to the expected hash given in the integrity value. - If the script or stylesheet doesn’t match its associated integrity value, then the browser must refuse to execute the script or apply the stylesheet, and must instead return a network error indicating that fetching of that script or stylesheet failed.
Specifications
| Specification | Status | Comment |
|---|---|---|
| Subresource Integrity | Recommendation | |
| Fetch | Living Standard |
Browser compatibility
<script integrity>
The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.
| Feature | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|---|
| Basic support | 45 | No | 43 | No | ? | No1 |
| Feature | Android webview | Chrome for Android | Edge mobile | Firefox for Android | Opera Android | iOS Safari | Samsung Internet |
|---|---|---|---|---|---|---|---|
| Basic support | 45 | 45 | No | 43 | ? | No | 5.0 |
1. WebKit bug 148363 tracks WebKit implementation of Subresource Integrity (which includes the integrity attribute).
CSP: require-sri-for
The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.
| Feature | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|---|
| Basic support | 54 | No | 491 | No | 41 | No |
| Feature | Android webview | Chrome for Android | Edge mobile | Firefox for Android | Opera Android | iOS Safari | Samsung Internet |
|---|---|---|---|---|---|---|---|
| Basic support | 54 | 54 | No | 491 | 41 | No | 6.0 |
1. From version 49: this feature is behind the security.csp.experimentalEnabled preference (needs to be set to true). To change preferences in Firefox, visit about:config.
See also
- Content Security Policy
Content-Security-Policy- A CDN that can not XSS you: Using Subresource Integrity