How to add Subresource Integrity (SRI)
Subresource Integrity (SRI) is a security feature that enables browsers to verify that resources 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 resource must match.
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.
Note: 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:
So oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC is the “hash” part, and the prefix sha384 indicates that it’s a sha384 hash.
Note: 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.
You can generate SRI hashes from the command-line with openssl using a command invocation such as this:
or with shasum using a command invocation such as this:
Notes:
The pipe-through- xxd step takes the hexadecimal output from shasum and converts it to binary.
The pipe-through- awk step is necessary because shasum will pass the hashed filename in its output to xxd. That can have disastrous consequences if the filename happens to have valid hex characters in it — because xxd will also decode that and pass it to base64.
Additionally, the SRI Hash Generator at https://www.srihash.org/ is an online tool you can use to generate SRI hashes.
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:
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:
You can also specify both script and style to mandate SRI for both kinds of file.
For subresource-integrity verification of a resource served from an origin other than the document in which it’s embedded, browsers additionally check the resource using Cross-Origin Resource Sharing (CORS), to ensure the origin serving the resource allows it to be shared with the requesting origin. Therefore, the resource must be served with an Access-Control-Allow-Origin header that allows the resource to be shared with the requesting origin; for example:
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.
Note: 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
So oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC is the “hash” part, and the prefix sha384 indicates that it’s a sha384 hash.
Note: 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 | awk '{ print $1 }' | xxd -r -p | base64
Notes:
The pipe-through- xxd step takes the hexadecimal output from shasum and converts it to binary.
The pipe-through- awk step is necessary because shasum will pass the hashed filename in its output to xxd. That can have disastrous consequences if the filename happens to have valid hex characters in it — because xxd will also decode that and pass it to base64.
Additionally, the SRI Hash Generator at https://www.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.
Cross-Origin Resource Sharing and Subresource Integrity
For subresource-integrity verification of a resource served from an origin other than the document in which it’s embedded, browsers additionally check the resource using Cross-Origin Resource Sharing (CORS), to ensure the origin serving the resource allows it to be shared with the requesting origin. Therefore, the resource must be served with an Access-Control-Allow-Origin header that allows the resource to be shared with the requesting origin; for example:
Access-Control-Allow-Origin: *
Updated on: 18/07/2022
Thank you!