Static Resource Integrity Verification
Recently, a JS static resource service used for compatibility with older browsers Polyfill.io CDN had its script content modified by the new domain owner. Without any warning, malicious code was injected into websites that included this resource, putting a large number of sites at risk of automatic redirects or being used for spam distribution.
Researchers found that the root cause of this type of problem is that developers trusted the content of an external static resource by default. Even if the website code did not change, the script executed when users visited the site was no longer the originally safe version.
When you rely on <script src="..."> to load third-party static resources, you must verify content integrity. Otherwise, trusting the script returned by the CDN without protection is equivalent to handing your website’s security over to the goodwill of an external service. Typically, static resource integrity verification is implemented in HTML files using Subresource Integrity (SRI).
SRI allows the browser to verify the integrity of a resource when loading it. It is a security feature that works by providing a hash value for the resource, so the browser can verify that the resource has not been tampered with when loading it.
How to use SRI
- Generate hash values
To use SRI, you first need to generate a hash value for the static resource. You can use the openssl tool to generate these hash values. Common hash algorithms include SHA-256, SHA-384, and SHA-512.
openssl dgst -sha384 -binary your-file.js | openssl base64 -A
For example, for a file named main.js, you can use the following command to generate a hash value:
openssl dgst -sha384 -binary main.js | openssl base64 -A
- Using SRI in HTML
After generating the hash, you can add it to the corresponding resource link in the HTML file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="styles.css" integrity="sha384-<generated-hash-value>" crossorigin="anonymous">
</head>
<body>
<script src="main.js" integrity="sha384-<generated-hash-value>" crossorigin="anonymous"></script>
</body>
</html>
- Automating SRI Hash Generation
For large projects, manually generating and managing SRI hashes may be impractical. You can use tools and plugins to automate this process.
Using the sri-hash Tool
sri-hash is a convenient command-line tool that can automatically generate SRI hashes.
Installation:
npm install -g sri-hash
Usage:
sri-hash main.js
Using the webpack Plugin.
If you use webpack for project builds, you can use the webpack-subresource-integrity plugin to automatically generate and inject SRI hashes.
Installation:
npm install webpack-subresource-integrity --save-dev
Use it in the webpack configuration:
const SriPlugin = require('webpack-subresource-integrity');
module.exports = {
// 其他配置...
output: {
crossOriginLoading: 'anonymous'
},
plugins: [
new SriPlugin({
hashFuncNames: ['sha256', 'sha384'],
enabled: process.env.NODE_ENV === 'production',
}),
],
};
- Verifying SRI functionality
After completing the configuration above, deploy the application and load the page. You can inspect network requests in the browser developer tools. If a resource’s hash does not match, the browser will refuse to load it and display an error in the console.
Notes
- Cross-origin resources: If a resource is cross-origin, ensure the resource server sets CORS headers to allow cross-origin requests.
- Caching: Make sure the resource is in its final version when generating the SRI hash to avoid mismatches caused by caching.
- Compatibility: Not all browsers support SRI; it is mainly supported by modern browsers.