1 | # webpack-subresource-integrity
|
---|
2 |
|
---|
3 | [![npm version](https://badge.fury.io/js/webpack-subresource-integrity.svg)](https://badge.fury.io/js/webpack-subresource-integrity) [![Travis Build Status](https://travis-ci.org/waysact/webpack-subresource-integrity.svg?branch=master)](https://travis-ci.org/waysact/webpack-subresource-integrity) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/63bydfph00sghg18/branch/master?svg=true)](https://ci.appveyor.com/project/jscheid/webpack-subresource-integrity) [![Coverage Status](https://coveralls.io/repos/github/waysact/webpack-subresource-integrity/badge.svg?branch=master)](https://coveralls.io/github/waysact/webpack-subresource-integrity?branch=master) [![Code Climate](https://codeclimate.com/github/waysact/webpack-subresource-integrity/badges/gpa.svg)](https://codeclimate.com/github/waysact/webpack-subresource-integrity) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/waysact/webpack-subresource-integrity/master/LICENSE)
|
---|
4 |
|
---|
5 | Webpack plugin for enabling Subresource Integrity.
|
---|
6 |
|
---|
7 | [Subresource Integrity](http://www.w3.org/TR/SRI/) (SRI) is a security
|
---|
8 | feature that enables browsers to verify that files they fetch (for
|
---|
9 | example, from a CDN) are delivered without unexpected
|
---|
10 | manipulation.
|
---|
11 |
|
---|
12 | ## Features
|
---|
13 |
|
---|
14 | - Optional integration with [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin).
|
---|
15 | - Automatic support for dynamic imports (also known as code splitting.)
|
---|
16 | - Compatible with all major Webpack versions, up to and including Webpack 5.
|
---|
17 |
|
---|
18 | ## Installation
|
---|
19 |
|
---|
20 | ```shell
|
---|
21 | npm install webpack-subresource-integrity --save-dev
|
---|
22 | ```
|
---|
23 |
|
---|
24 | ```shell
|
---|
25 | yarn add --dev webpack-subresource-integrity
|
---|
26 | ```
|
---|
27 |
|
---|
28 | ### Webpack Configuration Example
|
---|
29 |
|
---|
30 | ```javascript
|
---|
31 | import SriPlugin from 'webpack-subresource-integrity';
|
---|
32 |
|
---|
33 | const compiler = webpack({
|
---|
34 | output: {
|
---|
35 | crossOriginLoading: 'anonymous',
|
---|
36 | },
|
---|
37 | plugins: [
|
---|
38 | new SriPlugin({
|
---|
39 | hashFuncNames: ['sha256', 'sha384'],
|
---|
40 | enabled: process.env.NODE_ENV === 'production',
|
---|
41 | }),
|
---|
42 | ],
|
---|
43 | });
|
---|
44 | ```
|
---|
45 |
|
---|
46 | ### Setting the `integrity` attribute for top-level assets
|
---|
47 |
|
---|
48 | For the plugin to take effect it is **essential** that you set the
|
---|
49 | `integrity` attribute for top-level assets (i.e. assets loaded by your
|
---|
50 | HTML pages.)
|
---|
51 |
|
---|
52 | #### With HtmlWebpackPlugin
|
---|
53 |
|
---|
54 | When html-webpack-plugin is injecting assets into the template (the
|
---|
55 | default), the `integrity` attribute will be set automatically. The
|
---|
56 | `crossorigin` attribute will be set as well, to the value of
|
---|
57 | `output.crossOriginLoading` webpack option. There is nothing else to
|
---|
58 | be done.
|
---|
59 |
|
---|
60 | #### With HtmlWebpackPlugin({ inject: false })
|
---|
61 |
|
---|
62 | When you use html-webpack-plugin with `inject: false`, you are
|
---|
63 | required to set the `integrity` and `crossorigin` attributes in your
|
---|
64 | template as follows:
|
---|
65 |
|
---|
66 | ```ejs
|
---|
67 | <% for (var index in htmlWebpackPlugin.files.js) { %>
|
---|
68 | <script
|
---|
69 | src="<%= htmlWebpackPlugin.files.js[index] %>"
|
---|
70 | integrity="<%= htmlWebpackPlugin.files.jsIntegrity[index] %>"
|
---|
71 | crossorigin="<%= webpackConfig.output.crossOriginLoading %>"
|
---|
72 | ></script>
|
---|
73 | <% } %>
|
---|
74 |
|
---|
75 | <% for (var index in htmlWebpackPlugin.files.css) { %>
|
---|
76 | <link
|
---|
77 | rel="stylesheet"
|
---|
78 | href="<%= htmlWebpackPlugin.files.css[index] %>"
|
---|
79 | integrity="<%= htmlWebpackPlugin.files.cssIntegrity[index] %>"
|
---|
80 | crossorigin="<%= webpackConfig.output.crossOriginLoading %>"
|
---|
81 | />
|
---|
82 | <% } %>
|
---|
83 | ```
|
---|
84 |
|
---|
85 | #### Without HtmlWebpackPlugin
|
---|
86 |
|
---|
87 | The correct value for the `integrity` attribute can be retrieved from
|
---|
88 | the `integrity` property of Webpack assets.
|
---|
89 |
|
---|
90 | Note that with Webpack versions before 5, that property is not copied over by
|
---|
91 | Webpack's `stats` module so you'll have to access the "original" asset on the
|
---|
92 | `compilation` object. For example:
|
---|
93 |
|
---|
94 | ```javascript
|
---|
95 | compiler.plugin("done", stats => {
|
---|
96 | const mainAssetName = stats.toJson().assetsByChunkName.main;
|
---|
97 | const integrity = stats.compilation.assets[mainAssetName].integrity;
|
---|
98 | });
|
---|
99 | ```
|
---|
100 |
|
---|
101 | Note that you're also required to set the `crossorigin` attribute. It
|
---|
102 | is recommended to set this attribute to the same value as the webpack
|
---|
103 | `output.crossOriginLoading` configuration option.
|
---|
104 |
|
---|
105 | ### Web Server Configuration
|
---|
106 |
|
---|
107 | If your page can be loaded through plain HTTP (as opposed to HTTPS),
|
---|
108 | you must set the `Cache-Control: no-transform` response header or your
|
---|
109 | page will break when assets are loaded through a transforming
|
---|
110 | proxy. [See below](#proxies) for more information.
|
---|
111 |
|
---|
112 | ### Content Security Policy
|
---|
113 |
|
---|
114 | ~~Consider adding the following rule to your CSP file:~~
|
---|
115 |
|
---|
116 | ~~```Content-Security-Policy: require-sri-for script style;```~~
|
---|
117 |
|
---|
118 | ~~It ensures that if, for some reason, this plugin fails to add
|
---|
119 | integrity attributes to all your assets, your page will fail to load
|
---|
120 | rather than load with unverified assets.~~
|
---|
121 |
|
---|
122 | `require-sri-for` has never officially shipped in
|
---|
123 | [Chrome](https://bugs.chromium.org/p/chromium/issues/detail?id=618924)
|
---|
124 | or
|
---|
125 | [Firefox](https://groups.google.com/d/msg/mozilla.dev.platform/TKFsYlh9pr8/o_Vq_1s7BwAJ),
|
---|
126 | and both appear to be leaning towards removing their implementations.
|
---|
127 |
|
---|
128 | ### Options
|
---|
129 |
|
---|
130 | #### hashFuncNames
|
---|
131 |
|
---|
132 | Required option, no default value.
|
---|
133 |
|
---|
134 | An array of strings, each specifying the name of a hash function to be
|
---|
135 | used for calculating integrity hash values. For example, `['sha256',
|
---|
136 | 'sha512']`.
|
---|
137 |
|
---|
138 | See [SRI: Cryptographic hash functions](http://www.w3.org/TR/SRI/#cryptographic-hash-functions)
|
---|
139 |
|
---|
140 | #### enabled
|
---|
141 |
|
---|
142 | Default value: `true`
|
---|
143 |
|
---|
144 | When this value is falsy, the plugin doesn't run and no integrity
|
---|
145 | values are calculated. It is recommended to disable the plugin in
|
---|
146 | development mode.
|
---|
147 |
|
---|
148 | ## Exporting `integrity` values
|
---|
149 |
|
---|
150 | You might want to export generated integrity hashes, perhaps for use
|
---|
151 | with SSR. We recommend
|
---|
152 | [webpack-assets-manifest](https://github.com/webdeveric/webpack-assets-manifest)
|
---|
153 | for this purpose. When configured with option `integrity: true` it
|
---|
154 | will include the hashes generated by this plugin in the manifest
|
---|
155 | (requires webpack-assets-manifest version >= 3 which in turn requires
|
---|
156 | Webpack >= 4).
|
---|
157 |
|
---|
158 | [Example usage with webpack-assets-manifest](examples/webpack-assets-manifest/).
|
---|
159 |
|
---|
160 | ## Caveats
|
---|
161 |
|
---|
162 | ### Preloading
|
---|
163 |
|
---|
164 | This plugin adds the integrity attribute to `<link rel="preload">`
|
---|
165 | tags, but preloading with SRI doesn't work as expected in current
|
---|
166 | Chrome versions. The resource will be loaded twice, defeating the
|
---|
167 | purpose of preloading. This problem doesn't appear to exist in
|
---|
168 | Firefox or Safari. See [issue
|
---|
169 | #111](https://github.com/waysact/webpack-subresource-integrity/issues/111)
|
---|
170 | for more information.
|
---|
171 |
|
---|
172 | ### Proxies
|
---|
173 |
|
---|
174 | By its very nature, SRI can cause your page to break when assets are
|
---|
175 | modified by a proxy. This is because SRI doesn't distinguish between
|
---|
176 | malicious and benevolent modifications: any modification will prevent
|
---|
177 | an asset from being loaded.
|
---|
178 |
|
---|
179 | Notably, this issue can arise when your page is loaded through
|
---|
180 | [Chrome Data Saver](https://developer.chrome.com/multidevice/data-compression).
|
---|
181 |
|
---|
182 | This is only a problem when your page can be loaded with plain HTTP,
|
---|
183 | since proxies are incapable of modifying encrypted HTTPS responses.
|
---|
184 |
|
---|
185 | Presumably, you're looking to use SRI because you're concerned about
|
---|
186 | security and thus your page is only served through HTTPS anyway.
|
---|
187 | However, if you really need to use SRI and HTTP together, you should
|
---|
188 | set the `Cache-Control: no-transform` response header. This will
|
---|
189 | instruct all well-behaved proxies (including Chrome Data Saver) to
|
---|
190 | refrain from modifying the assets.
|
---|
191 |
|
---|
192 | ### Browser support
|
---|
193 |
|
---|
194 | Browser support for SRI is widely implemented. Your page will still
|
---|
195 | work on browsers without support for SRI, but subresources won't be
|
---|
196 | protected from tampering.
|
---|
197 |
|
---|
198 | See [Can I use Subresource Integrity?](http://caniuse.com/#feat=subresource-integrity)
|
---|
199 |
|
---|
200 | ### Hot Reloading
|
---|
201 |
|
---|
202 | This plugin can interfere with hot reloading and therefore should be
|
---|
203 | disabled when using tools such as `webpack-dev-server`. This shouldn't
|
---|
204 | be a problem because hot reloading is usually used only in development
|
---|
205 | mode where SRI is not normally needed.
|
---|
206 |
|
---|
207 | For testing SRI without setting up a full-blown web server, consider
|
---|
208 | using a tool such as [`http-server`](https://github.com/indexzero/http-server).
|
---|
209 |
|
---|
210 | ### Safari and Assets that Require Cookies
|
---|
211 |
|
---|
212 | As detailed in
|
---|
213 | [Webpack Issue #6972](https://github.com/webpack/webpack/issues/6972),
|
---|
214 | the `crossOrigin` attribute can break loading of assets in certain
|
---|
215 | edge cases due to a bug in Safari. Since SRI requires the
|
---|
216 | `crossOrigin` attribute to be set, you may run into this case even
|
---|
217 | when source URL is same-origin with respect to the asset.
|
---|
218 |
|
---|
219 | ## Further Reading
|
---|
220 |
|
---|
221 | - [MDN: Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)
|
---|
222 |
|
---|
223 | ## License
|
---|
224 |
|
---|
225 | Copyright (c) 2015-present Waysact Pty Ltd
|
---|
226 |
|
---|
227 | MIT (see [LICENSE](LICENSE))
|
---|