webpack-subresource-integrity
5.2.0-rc.1 • Public • Publishedwebpack-subresource-integrity
Webpack plugin for enabling Subresource Integrity.
Subresource Integrity (SRI) is a securityfeature that enables browsers to verify that files they fetch (forexample, from a CDN) are delivered without unexpectedmanipulation.
Upgrading from version 1.x?Read the migration guide.
Features
- Optional integration withhtml-webpack-plugin.
- Automatic support for dynamic imports (also known as code splitting.)
- Compatible with Webpack 5 (for Webpack versions 1-4 see1.x branch.)
Installation
yarn add --dev webpack-subresource-integrity
npm install webpack-subresource-integrity --save-dev
Recommended Webpack Configuration
import{SubresourceIntegrityPlugin}from"webpack-subresource-integrity";// or: const { SubresourceIntegrityPlugin } = require('webpack-subresource-integrity');constcompiler=webpack({output:{// the following setting is required for SRI to work:crossOriginLoading:"anonymous",},plugins:[newSubresourceIntegrityPlugin()],});
integrity
attribute for top-level assets
Setting theFor the plugin to take effect it isessential that you set theintegrity
attribute for top-level assets (i.e. assets loaded by yourHTML pages.)
With HtmlWebpackPlugin
When html-webpack-plugin is injecting assets into the template (thedefault), theintegrity
attribute will be set automatically. Thecrossorigin
attribute will be set as well, to the value ofoutput.crossOriginLoading
webpack option. There is nothing else tobe done.
With HtmlWebpackPlugin({ inject: false })
When you use html-webpack-plugin withinject: false
, you arerequired to set theintegrity
andcrossorigin
attributes in yourtemplate as follows:
<%for (let indexinhtmlWebpackPlugin.files.js) {%><script src="<%= htmlWebpackPlugin.files.js[index] %>" integrity="<%= htmlWebpackPlugin.files.jsIntegrity[index] %>" crossorigin="<%= webpackConfig.output.crossOriginLoading %>"></script><% }%><%for (let indexinhtmlWebpackPlugin.files.css) {%><link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[index] %>" integrity="<%= htmlWebpackPlugin.files.cssIntegrity[index] %>" crossorigin="<%= webpackConfig.output.crossOriginLoading %>"/><% }%>
Without HtmlWebpackPlugin
The correct value for theintegrity
attribute can be retrieved fromtheintegrity
property of Webpack assets. For example:
compiler.plugin("done",(stats)=>{constintegrityValues=stats.toJson().assets.map((asset)=>[asset.name,asset.integrity]);});
Note that when you add theintegrity
attribute on yourlink
andscript
tags, you're also required to set thecrossorigin
attribute. It is recommended to set this attribute to the same valueas the webpackoutput.crossOriginLoading
configuration option.
Web Server Configuration
If your page can be loaded through plain HTTP (as opposed to HTTPS),you must set theCache-Control: no-transform
response header or yourpage will break when assets are loaded through a transformingproxy.See below for more information.
When using caching, stale assets will fail to load since they will not passintegrity checks. It is vital that you configure caching correctly in your webserver.See below for more information.
Options
hashFuncNames
Default value:["sha384"]
An array of strings, each specifying the name of a hash function to beused for calculating integrity hash values.
SeeSRI: Cryptographic hash functions
The default is chosen based on the currentsuggestion by theW3C whichreads:
At the time of writing, SHA-384 is a good baseline.
Seehere for additionalinformation on why SHA-384 was chosen by the W3C over their initial suggestion,SHA-256.
As one of the commenters in that discussion points out, "SRI hashes are likelydelivered over SSL" which today (2021) is often using SHA-256 so that there isprobably little harm in downgrading this tosha256
instead.
By using SHA-256 you will save 21 bytes per chunk and perhaps a few CPU cycles,although SHA-384 is actually faster to compute on some hardware. Not that itmatters, as the difference is dwarfed by all the other work a browser has to doin order to download and parse a JS or CSS asset.
You probably want to usesha512
instead of the default only if you'reparanoid. It will cost you an additional 21 bytes per chunk; the CPU overhead isvirtually nil because SHA-512 is the same as SHA-384, just not truncated.
Although you can specify multiple hash functions here, doing so is pointless aslong as all mainstream browsers only support the SHA-2 family, which is the casetoday. Worse, it's detrimental since it adds unnecessary overhead.
The reason is that as per the spec, only the strongest hash function is used andso eg.['sha256', 'sha512']
is equivalent to['sha512']
unless SHA-512 wasone day deemedweaker than SHA-256 by user agents, which is an unlikelyscenario. As one of the authors of the W3C specputsit:
The support for multiple hashes is in the spec for backward-compatibility oncewe introduce new hash algorithms (e.g. SHA3).
enabled
Default value:"auto"
One of"auto"
,true
, orfalse
.
true
means to enable the plugin andfalse
means to disable it.
auto
is the default and means to enable the plugin when theWebpackmode isproduction
ornone
and disable it when it isdevelopment
.
hashLoading
Default value:"eager"
One of"eager"
or"lazy"
"eager"
means that integrity hashes for all assets will be defined in the entry chunk.
"lazy"
means that integrity hashes for any given asset will be defined in its direct parentsin the chunk graph. This can lead to duplication of hashes across assets, but can significantlyreduce the size of your entry chunk(s) if you have a large number of async chunks.
integrity
values
ExportingYou might want to export generated integrity hashes, perhaps for usewith SSR. We recommendwebpack-assets-manifestfor this purpose. When configured with optionintegrity: true
itwill include the hashes generated by this plugin in the manifest.
Example usage with webpack-assets-manifest.
Caveats
Caching
Using SRI presents a potential risk to the availability of your website whenHTTP response caching is setup incorrectly. Stale asset versions are alwaysproblematic but SRI exacerbates the risk.
Without SRI, inconsequential changes (such as whitespace-only changes) don'tmatter, and your website might still look OK when a stale CSS asset is used.Even with a stale JS asset there's a chance your website will still be more orless working as expected.
With SRI, however, a stale asset will fail hard. This is because the browserwon't tell the difference between a version of your asset that has been tamperedwith and one that is simply outdated: both will fail the integrity check andrefuse to load.
It's therefore imperative that, if you do use caching, you use a robust setup:one whereany change in content, no matter how miniscule or inconsequential,will cause the cache to be invalidated.
With Webpack and long-term caching this means using[contenthash]
(withrealContentHash
, which is enabled by default in production mode). Using[contenthash]
withrealContentHash
disabled, or using a different type ofhash placeholder (such as[chunkhash]
) provides weaker guarantees, which iswhy this plugin will output a warning in these cases. Seeissue#162for more information.
Proxies
By its very nature, SRI can cause your page to break when assets aremodified by a proxy. This is because SRI doesn't distinguish betweenmalicious and benevolent modifications: any modification will preventan asset from being loaded.
Notably, this issue can arise when your page is loaded throughChrome Data Saver.
This is only a problem when your page can be loaded with plain HTTP,since proxies are incapable of modifying encrypted HTTPS responses.
Presumably, you're looking to use SRI because you're concerned aboutsecurity and thus your page is only served through HTTPS anyway.However, if you really need to use SRI and HTTP together, you shouldset theCache-Control: no-transform
response header. This willinstruct all well-behaved proxies (including Chrome Data Saver) torefrain from modifying the assets.
Preloading
This plugin adds the integrity attribute to<link rel="preload">
tags, but preloading with SRI doesn't work as expected in currentChrome versions. The resource will be loaded twice, defeating thepurpose of preloading. This problem doesn't appear to exist inFirefox or Safari. Seeissue#111for more information.
Browser support
Browser support for SRI is widely implemented. Your page will stillwork on browsers without support for SRI, but subresources won't beprotected from tampering.
SeeCan I use Subresource Integrity?
Hot Reloading
This plugin can interfere with hot reloading and therefore should bedisabled when using tools such aswebpack-dev-server
. This shouldn'tbe a problem because hot reloading is usually used only in developmentmode where SRI is not normally needed.
For testing SRI without setting up a full-blown web server, considerusing a tool such ashttp-server
.
Safari 13 (and earlier versions) and Assets that Require Cookies
As detailed inWebpack Issue#6972, thecrossOrigin
attribute can break loading of assets in Safari versions prior to 14 in certainedge cases due to a browser bug. Since SRI requires thecrossOrigin
attributeto be set, you may run into this case even when source URL is same-origin withrespect to the asset. The fix for this issue landed in Safari Technology Preview106 and was released with Safari 14
Further Reading
License
Copyright (c) 2015-present Waysact Pty Ltd
MIT (seeLICENSE)
Package Sidebar
Install
npm i webpack-subresource-integrity
Homepage
github.com/waysact/webpack-subresource-integrity/tree/main/webpack-subresource-integrity#readme
Weekly Downloads
3,865,273
Version
5.2.0-rc.1
License
MIT
Unpacked Size
283 kB
Total Files
125