Subresource Integrity (SRI) is a neat security feature that helps browsers make sure the files they fetch, like scripts from a CDN, haven't been tampered with. Essentially, it lets you set up a cryptographic hash that the fetched file must match. If the retrieved file’s integrity doesn't match the hash you provided, the browser will not load it, discarding it as if it failed to fetch in the first place. This is a solid way to guard against resource hijacking.
Alright, let's dive into how you can use SRI tags in JavaScript to keep those pesky malicious scripts at bay, step by step:
Get the Resource Hash:
First things first, you need the cryptographic hash of the resource you want to load. This hash is what will be used to verify the file’s integrity.
You can get this hash using command-line tools like shasum
or even online resources.
For instance, with shasum
:
curl https://cdn.example.com/script.js | shasum -a 384
Running this command will give you an output like:
abc123def456... -
Choose the Right Hash Algorithm:
The commonly used hash algorithms are:
It’s generally better to go with a stronger one like SHA-384
or SHA-512
.
Incorporate the SRI Hash in HTML:
Now that you've got the hash, you can plug it into your HTML using the integrity
attribute. Don’t forget the crossorigin
attribute if the file is being loaded from a different origin.
<script src="https://cdn.example.com/script.js"
integrity="sha384-Abc123Def456..."
crossorigin="anonymous"></script>
Imagine you’re loading jQuery from a CDN.
Generate the SRI Hash:
First, you’ll want to download and hash the jQuery file. For example:
curl https://code.jquery.com/jquery-3.6.0.min.js | shasum -a 384
This command might give:
sha384-9/aliU8dGd2tb6OSsuzixeV4y/faTqgf Ftohetphbbj0= . -
Apply the Hash in HTML:
Next, place the hash in the integrity
attribute within your HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secure Script Loading</title>
</head>
<body>
<!-- Load jQuery library with SRI and crossorigin attributes -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha384-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"></script>
<script>
// Your custom JavaScript code here
$(document).ready(function(){
console.log("jQuery and custom scripts loaded securely!");
});
</script>
</body>
</html>
Updating Resources:
If you update the hosted resource, don’t forget to update the integrity value too. Otherwise, the browser will reject the new resource.
Cross-Origin Resource Sharing (CORS):
Use the crossorigin
attribute with SRI. Without it, the integrity check might fail. Usually, set it to anonymous
unless your requests need credentials.
Error Handling:
If a resource fails the integrity check, it's treated as a failed load. Make sure your app can handle these scenarios smoothly.
Performance:
SRI can slightly impact loading times due to the extra hash verification, but the security benefits more than make up for this minor cost.
Host Integrity Verification:
Trust the CDN or host where you're fetching resources from. SRI guards against tampering during transit, but not against malicious scripts right at the source.
Using SRI in a Build Process:
You can automate the SRI hash generation and insertion in HTML during your build process using tools like webpack or gulp.
Webpack Example:
Install webpack and webpack-subresource-integrity-plugin
:
npm install --save-dev webpack webpack-cli webpack-subresource-integrity
Configure webpack.config.js
:
const SubresourceIntegrityPlugin = require('webpack-subresource-integrity');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist',
crossOriginLoading: 'anonymous'
},
plugins: [
new SubresourceIntegrityPlugin({
hashFuncNames: ['sha384'],
enabled: true
}),
],
};
Include the Output in Your HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Webpack SRI</title>
</head>
<body>
<script src="dist/bundle.js"></script>
</body>
</html>
Incorporating SRI checks into your development and deployment process is like putting a lock on the doors and windows of your app, ensuring that everything’s safe and sound from nasty tampering threats. It takes some mindful planning and, of course, keeping things updated, but it's a worthy investment for your web app's overall security.