[6a3a178] | 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))
|
---|