|
1 | 1 | # webpack-subresource-integrity
|
2 | 2 |
|
3 |
| -[](https://travis-ci.org/waysact/webpack-subresource-integrity) |
| 3 | +[](https://badge.fury.io/js/webpack-subresource-integrity) [](https://travis-ci.org/waysact/webpack-subresource-integrity) [](https://david-dm.org/waysact/webpack-subresource-integrity) [](https://raw.githubusercontent.com/waysact/webpack-subresource-integrity/master/LICENSE) |
4 | 4 |
|
5 |
| -A Webpack plugin for ensuring |
6 |
| -[subresource integrity](http://www.w3.org/TR/SRI/) on |
7 |
| -[supported browsers](http://caniuse.com/#feat=subresource-integrity). |
| 5 | +Webpack plugin for enabling Subresource Integrity. |
8 | 6 |
|
9 |
| -Integrity is ensured automatically for lazy-loaded chunks (loaded via |
10 |
| -`require.ensure`). |
| 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 | 11 |
|
12 |
| -It's your responsibility to include the `integrity` attribute in the |
13 |
| -HTML for top-level chunks. Obviously, SRI for lazy-loaded chunks is |
14 |
| -pointless unless integrity of the top-level chunks is ensured as well. |
| 12 | +## Features |
15 | 13 |
|
16 |
| -[html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin) |
17 |
| -users can get the `integrity` attribute set automatically, see below. |
| 14 | +- Integration with [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin) |
| 15 | +- Support for code-splitting (integrity for lazy-loaded chunks) |
18 | 16 |
|
19 |
| -## Usage |
| 17 | +## Installation |
20 | 18 |
|
21 |
| -### Installing the Plugin |
22 |
| - |
23 |
| - $ npm install webpack-subresource-integrity --save-dev |
| 19 | +```shell |
| 20 | +npm install webpack-subresource-integrity --save-dev |
| 21 | +``` |
24 | 22 |
|
25 |
| -Pass an array of |
26 |
| -[hash algorithms](http://www.w3.org/TR/SRI/#cryptographic-hash-functions) |
27 |
| -to the plugin constructor: |
| 23 | +### Webpack Configuration Example |
28 | 24 |
|
29 |
| - import SriPlugin from 'webpack-subresource-integrity'; |
| 25 | +```javascript |
| 26 | +import SriPlugin from 'webpack-subresource-integrity'; |
30 | 27 |
|
31 |
| - const compiler = webpack({ |
32 |
| - plugins: [ |
33 |
| - // ... |
34 |
| - new SriPlugin(['sha256', 'sha384']), |
35 |
| - ], |
36 |
| - }); |
| 28 | +const compiler = webpack({ |
| 29 | + plugins: [ |
| 30 | + new SriPlugin({ |
| 31 | + hashFuncNames: ['sha256', 'sha384'], |
| 32 | + enabled: process.env.NODE_ENV === 'production', |
| 33 | + crossorigin: 'anonymous', |
| 34 | + }), |
| 35 | + ], |
| 36 | +}); |
| 37 | +``` |
37 | 38 |
|
38 |
| -### Accessing the `integrity` Value for Top-level Assets |
| 39 | +### Setting the `integrity` attribute for top-level assets |
39 | 40 |
|
40 |
| -The correct value for the `integrity` attribute can be retrieved from |
41 |
| -the `integrity` property of webpack assets. However, that property is |
42 |
| -not copied over by webpack's `stats` module so you'll have to access |
43 |
| -the "original" asset on the `compilation` object. Something like |
44 |
| -this: |
| 41 | +For the plugin to take effect it is **essential** that you set the |
| 42 | +`integrity` attribute for top-level assets (i.e. assets loaded by your |
| 43 | +HTML pages.) |
45 | 44 |
|
46 |
| - compiler.plugin("done", stats => { |
47 |
| - var integrity = stats.compilation.assets[stats.toJson().assetsByChunkName.main].integrity; |
48 |
| - }); |
| 45 | +#### With HtmlWebpackPlugin |
49 | 46 |
|
50 |
| -Use that value to generate the `integrity` attribute for tags such as |
51 |
| -`<script>` and `<link>`. Note that you are also |
52 |
| -[required to set the `crossorigin` attribute](https://www.w3.org/TR/SRI/#cross-origin-data-leakage). |
| 47 | +When html-webpack-plugin is injecting assets into the template (the |
| 48 | +default), the `integrity` attribute will be set automatically. There |
| 49 | +is nothing else to be done. |
53 | 50 |
|
54 |
| -#### `html-webpack-plugin` Integration |
| 51 | +#### With HtmlWebpackPlugin({ inject: false }) |
55 | 52 |
|
56 |
| -The plugin installs a hook for `html-webpack-plugin` that adds the |
57 |
| -`integrity` attribute automatically when `inject: true` (the default). |
58 |
| -This requires `html-webpack-plugin` version `2.21.0` or later. The |
59 |
| -`crossorigin` attribute will be set to `anonymous` in this case. |
60 |
| - |
61 |
| -If you're using a template with `html-webpack-plugin` and with |
62 |
| -`inject: false`, you can generate the attributes as follows: |
| 53 | +When you use html-webpack-plugin with `inject: false`, you are |
| 54 | +required to set the `integrity` and `crossorigin` attributes in your |
| 55 | +template as follows: |
63 | 56 |
|
64 | 57 | ```ejs
|
65 | 58 | <% for (var index in htmlWebpackPlugin.files.js) { %>
|
66 |
| - <script src="<%= htmlWebpackPlugin.files.js[index] %>" |
67 |
| - integrity="<%= htmlWebpackPlugin.files.jsIntegrity[index] %>" |
68 |
| - crossorigin="anonymous" |
| 59 | + <script |
| 60 | + src="<%= htmlWebpackPlugin.files.js[index] %>" |
| 61 | + integrity="<%= htmlWebpackPlugin.files.jsIntegrity[index] %>" |
| 62 | + crossorigin="<%= htmlWebpackPlugin.options.sriCrossOrigin %>" |
69 | 63 | ></script>
|
70 | 64 | <% } %>
|
71 | 65 |
|
72 | 66 | <% for (var index in htmlWebpackPlugin.files.css) { %>
|
73 |
| - <link href="<%= htmlWebpackPlugin.files.css[index] %>" |
74 |
| - integrity="<%= htmlWebpackPlugin.files.cssIntegrity[index] %>" |
75 |
| - rel="stylesheet" |
76 |
| - crossorigin="anonymous" |
77 |
| - > |
| 67 | + <link |
| 68 | + href="<%= htmlWebpackPlugin.files.css[index] %>" |
| 69 | + integrity="<%= htmlWebpackPlugin.files.cssIntegrity[index] %>" |
| 70 | + crossorigin="<%= htmlWebpackPlugin.options.sriCrossOrigin %>" |
| 71 | + rel="stylesheet" |
| 72 | + /> |
78 | 73 | <% } %>
|
79 | 74 | ```
|
80 | 75 |
|
| 76 | +#### Without HtmlWebpackPlugin |
| 77 | + |
| 78 | +The correct value for the `integrity` attribute can be retrieved from |
| 79 | +the `integrity` property of Webpack assets. However, that property is |
| 80 | +not copied over by Webpack's `stats` module so you'll have to access |
| 81 | +the "original" asset on the `compilation` object. For example: |
| 82 | + |
| 83 | +```javascript |
| 84 | +compiler.plugin("done", stats => { |
| 85 | + const mainAssetName = stats.toJson().assetsByChunkName.main; |
| 86 | + const integrity = stats.compilation.assets[mainAssetName].integrity; |
| 87 | +}); |
| 88 | +``` |
| 89 | + |
| 90 | +### Options |
| 91 | + |
| 92 | +#### hashFuncNames |
| 93 | + |
| 94 | +Required option, no default value. |
| 95 | + |
| 96 | +An array of strings, each specifying the name of a hash function to be |
| 97 | +used for calculating integrity hash values. For example, `['sha256', |
| 98 | +'sha512']`. |
| 99 | + |
| 100 | +See [SRI: Cryptographic hash functions](http://www.w3.org/TR/SRI/#cryptographic-hash-functions) |
| 101 | + |
| 102 | +#### enabled |
| 103 | + |
| 104 | +Default value: `true` |
| 105 | + |
| 106 | +When this value is falsy, the plugin doesn't run and no integrity |
| 107 | +values are calculated. It is recommended to disable the plugin in |
| 108 | +development mode. |
| 109 | + |
| 110 | +#### crossorigin |
| 111 | + |
| 112 | +Default value: `"anonymous"` |
| 113 | + |
| 114 | +When using `HtmlWebpackPlugin({ inject: true })`, this option |
| 115 | +specifies the value to be used for the `crossorigin` attribute for |
| 116 | +injected assets. |
| 117 | + |
| 118 | +The value will also be available as |
| 119 | +`htmlWebpackPlugin.options.sriCrossOrigin` in html-webpack-plugin |
| 120 | +templates. |
| 121 | + |
| 122 | +See |
| 123 | +[SRI: Cross-origin data leakage](https://www.w3.org/TR/SRI/#cross-origin-data-leakage) and |
| 124 | +[MDN: CORS settings attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) |
| 125 | + |
81 | 126 | ## Caveats
|
82 | 127 |
|
83 |
| -* There is a |
84 |
| - [known bug relating to SRI in Chrome versions before 47](https://code.google.com/p/chromium/issues/detail?id=527286) |
85 |
| - which will break loading of scripts containing certain UTF-8 |
86 |
| - characters. You might want to hold off using SRI if you need to |
87 |
| - support older Chrome versions. |
| 128 | +### Browser support |
| 129 | + |
| 130 | +Browser support for SRI is currently patchy. Your page will still |
| 131 | +work on browsers without support for SRI, but subresources won't be |
| 132 | +protected from tampering. |
| 133 | + |
| 134 | +See [Can I use Subresource Integrity?](http://caniuse.com/#feat=subresource-integrity) |
| 135 | + |
| 136 | +### Broken browser versions |
| 137 | + |
| 138 | +There is a |
| 139 | +[known bug relating to SRI in Chrome 45 and 46](https://code.google.com/p/chromium/issues/detail?id=527286) |
| 140 | +which will break loading of scripts containing certain UTF-8 |
| 141 | +characters. You might want to hold off using SRI if you need to |
| 142 | +support these Chrome versions. (Unfortunately, Chrome 45 still |
| 143 | +[holds a relatively high market share](https://www.netmarketshare.com/report.aspx?qprid=3&qpaf=&qpcustom=Chrome+45.0&qpcustomb=0) |
| 144 | +of around 5% at the time of this writing.) |
88 | 145 |
|
89 |
| -## Contributing |
| 146 | +### Hot Module Replacement |
90 | 147 |
|
91 |
| -If you have discovered a bug or have a feature suggestion, feel free to create an issue on Github. |
| 148 | +Chunks loaded via Hot Module Replacement (HMR) are not currently |
| 149 | +protected. This shouldn't be a problem because HMR is usually used |
| 150 | +only in development mode where SRI is not normally needed. |
92 | 151 |
|
93 |
| -Pull requests are welcome. Please run `npm test` and `npm run lint` on |
94 |
| -your branch before submitting it. |
| 152 | +## Further Reading |
95 | 153 |
|
96 |
| -You are also welcome to correct any spelling mistakes or any language issues. |
| 154 | +- [MDN: Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) |
97 | 155 |
|
98 | 156 | ## License
|
99 | 157 |
|
100 | 158 | Copyright (c) 2015, 2016 Waysact Pty Ltd
|
101 | 159 |
|
102 |
| -MIT (see [`LICENSE`](LICENSE)) |
| 160 | +MIT (see [LICENSE](LICENSE)) |
0 commit comments