Skip to content

Commit

Permalink
Merge 05e996f into d7ef757
Browse files Browse the repository at this point in the history
  • Loading branch information
jscheid committed Sep 9, 2018
2 parents d7ef757 + 05e996f commit 1ead719
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 27 deletions.
11 changes: 8 additions & 3 deletions .travis.yml
Expand Up @@ -11,10 +11,13 @@ env:
- WEBPACK_SUFFIX="@2" ETWP_SUFFIX="@2" HWP_SUFFIX="@2"
- WEBPACK_SUFFIX="@3" ETWP_SUFFIX="@3" HWP_SUFFIX="@2"
- WEBPACK_SUFFIX="@4" ETWP_SUFFIX="@4.0.0-alpha.0" HWP_SUFFIX="@3"
- WEBPACK_SUFFIX="@4" ETWP_SUFFIX="@4.0.0-alpha.0" HWP_SUFFIX="@4.0.0-alpha.2"
matrix:
exclude:
- node_js: 4
env: WEBPACK_SUFFIX="@4" ETWP_SUFFIX="@4.0.0-alpha.0" HWP_SUFFIX="@3"
- node_js: 4
env: WEBPACK_SUFFIX="@4" ETWP_SUFFIX="@4.0.0-alpha.0" HWP_SUFFIX="@4.0.0-alpha.2"
install:
- npm install || true
- npm rm webpack
Expand All @@ -27,6 +30,8 @@ before_script:
- sh -e /etc/init.d/xvfb start
script:
- ./node_modules/karma/bin/karma start --single-run --browsers Firefox
- $(npm bin)/nyc --reporter=lcovonly $(npm bin)/mocha --exit --timeout 20000
after_script:
- $(npm bin)/travis-after-all && $(npm bin)/coveralls < ./coverage/lcov.info
- $(npm bin)/nyc $(npm bin)/mocha --exit --timeout 20000 && $(npm bin)/nyc report --reporter=text-lcov | $(npm bin)/coveralls
notifications:
webhooks:
# https://coveralls.io/webhook?repo_token=$(COVERALLS_REPO_TOKEN)
- secure: "pgSdpewaCRSR/R2MKf7PL8r/OmONltX2XA9NqMPM7sYiTdACL3ilFst1zpTDAQ015cjAp+g1dfhTuQbtEmT+yF3PikQ7TOTO7T65wHrMy5JV9E41tHm2IMgk4C92nOdljMTRcAW1Ra9R7SCL5yu9Fz42yfxo/YmJav6BXNi7sY9eXX/nqaPBXjfU8m5Oz7U7NwXMULm6C3Zs/UaMtGkZYwHxRDuwyz3f4LEZApC90uNb33gQukyX8NIqZbo25/ynGyTnQYHGQ8RaHBdvy1yRfC8lzRBkKxSuLtgfQVqbKOcqdu77rIwtInAmLxBEd/5RdTFSibz2iFd9MgauKB2tyQjSseOtoEVfCo17cRkCZHgLorXpqFP6cv0uRvsaedo9SlZE9h3HVDBPJBwgRILWbXMml3vhhZ4uQO+q1NTiGQ7dpqWRDHn9Ot+GB5wHZGmmNkvRmaxSzuhHQgaYOd+lSl1j2TZ56mRv+3JEcuCTgQXMz/pJ3oHlvAGP0iVVsMGjiH8xL9JIoBpjboPKIrHNE9k5zScubEgtnEGbjggNKGA8+kuovY1TcCAOoMnDeV8gTuDxFZtuKfHa6w1m96tFlGf+SEvLTEQ0iwDKix21jXFPw5fKgA9/Nk7MXyNVSo7zf8XhDLm8lzzTKXpkqqeSONuJaRz9haJ0RdtpOEmaD4c="
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -163,6 +163,15 @@ mode where SRI is not normally needed.
For testing SRI without setting up a full-blown web server, consider
using a tool such as [`http-server`](https://github.com/indexzero/http-server).

### Safari and Assets that Require Cookies

As detailed in [Webpack Issue
#6972](https://github.com/webpack/webpack/issues/6972), the
`crossOrigin` attribute can break loading of assets in certain edge
cases due to a bug in Safari. Since SRI requires the `crossOrigin`
attribute to be set, you may run into this case even when source URL
is same-origin with respect to the asset.

## Further Reading

- [MDN: Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)
Expand Down
15 changes: 15 additions & 0 deletions appveyor.yml
Expand Up @@ -36,6 +36,11 @@ environment:
ETWP_SUFFIX: "@4.0.0-alpha.0"
FL_SUFFIX: "@1"
HWP_SUFFIX: "@3"
- nodejs_version: 6
WEBPACK_SUFFIX: "@4"
ETWP_SUFFIX: "@4.0.0-alpha.0"
FL_SUFFIX: "@1"
HWP_SUFFIX: "@4.0.0-alpha.2"
- nodejs_version: 8
WEBPACK_SUFFIX: "@1"
ETWP_SUFFIX: "@1"
Expand All @@ -56,6 +61,11 @@ environment:
ETWP_SUFFIX: "@4.0.0-alpha.0"
FL_SUFFIX: "@1"
HWP_SUFFIX: "@3"
- nodejs_version: 8
WEBPACK_SUFFIX: "@4"
ETWP_SUFFIX: "@4.0.0-alpha.0"
FL_SUFFIX: "@1"
HWP_SUFFIX: "@4.0.0-alpha.2"
- nodejs_version: 10
WEBPACK_SUFFIX: "@1"
ETWP_SUFFIX: "@1"
Expand All @@ -76,6 +86,11 @@ environment:
ETWP_SUFFIX: "@4.0.0-alpha.0"
FL_SUFFIX: "@1"
HWP_SUFFIX: "@3"
- nodejs_version: 10
WEBPACK_SUFFIX: "@4"
ETWP_SUFFIX: "@4.0.0-alpha.0"
FL_SUFFIX: "@1"
HWP_SUFFIX: "@4.0.0-alpha.2"

# Install scripts. (runs after repo cloning)
install:
Expand Down
7 changes: 7 additions & 0 deletions examples/warn-checksum/test.js
@@ -1,4 +1,11 @@
var expect = require('expect');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports.skip = function skip() {
// Not sure how to provoke this warning with HWP 4
// Consider removing this test altogether.
return HtmlWebpackPlugin.version >= 4;
};

module.exports.check = function check(stats) {
expect(stats.compilation.warnings.length).toEqual(1);
Expand Down
3 changes: 3 additions & 0 deletions examples/webpack4-contenthash/README.md
@@ -0,0 +1,3 @@
# Ensure contenthash path variable works in Webpack 4.3+

Test case for issue #78
1 change: 1 addition & 0 deletions examples/webpack4-contenthash/chunk.js
@@ -0,0 +1 @@
console.log('ok');
3 changes: 3 additions & 0 deletions examples/webpack4-contenthash/index.js
@@ -0,0 +1,3 @@
require.ensure([], require => {
require('./chunk.js');
});
12 changes: 12 additions & 0 deletions examples/webpack4-contenthash/test.js
@@ -0,0 +1,12 @@
var webpackVersionComponents = require('webpack/package.json').version.split(
'.'
);
var webpackVersionMajor = Number(webpackVersionComponents[0]);
var webpackVersionMinor = Number(webpackVersionComponents[0]);

module.exports.skip = function skip() {
return (
webpackVersionMajor < 4 ||
(webpackVersionMajor === 4 && webpackVersionMinor < 3)
);
};
18 changes: 18 additions & 0 deletions examples/webpack4-contenthash/webpack.config.js
@@ -0,0 +1,18 @@
var SriPlugin = require("webpack-subresource-integrity");
var HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
entry: "./index.js",
mode: "production",
output: {
filename: "[name].[contenthash].js",
chunkFilename: "[name].[contenthash].js",
crossOriginLoading: "anonymous"
},
plugins: [
new HtmlWebpackPlugin(),
new SriPlugin({
hashFuncNames: ["sha256", "sha384"]
})
]
};
71 changes: 50 additions & 21 deletions index.js
Expand Up @@ -10,10 +10,20 @@ var path = require('path');
var ReplaceSource = require('webpack-core/lib/ReplaceSource');
var util = require('./util');
var WebIntegrityJsonpMainTemplatePlugin = require('./jmtp');
var HtmlWebpackPlugin;

// https://www.w3.org/TR/2016/REC-SRI-20160623/#cryptographic-hash-functions
var standardHashFuncNames = ['sha256', 'sha384', 'sha512'];

try {
// eslint-disable-next-line global-require
HtmlWebpackPlugin = require('html-webpack-plugin');
} catch (e) {
if (!(e instanceof Error) || e.code !== 'MODULE_NOT_FOUND') {
throw e;
}
}

function SubresourceIntegrityPlugin(options) {
var useOptions;
if (options === null || typeof options === 'undefined') {
Expand Down Expand Up @@ -231,30 +241,31 @@ SubresourceIntegrityPlugin.prototype.afterOptimizeAssets =
});
};

SubresourceIntegrityPlugin.prototype.processTag =
function processTag(compilation, tag) {
var src = this.hwpAssetPath(util.getTagSrc(tag));
var checksum = util.getIntegrityChecksumForAsset(compilation.assets, src);
if (!checksum) {
this.warnOnce(
compilation,
'Cannot determine hash for asset \'' +
src + '\', the resource will be unprotected.');
return;
}
// Add integrity check sums

/* eslint-disable no-param-reassign */
tag.attributes.integrity = checksum;
tag.attributes.crossorigin = compilation.compiler.options.output.crossOriginLoading || 'anonymous';
/* eslint-enable no-param-reassign */
};

SubresourceIntegrityPlugin.prototype.alterAssetTags =
function alterAssetTags(compilation, pluginArgs, callback) {
/* html-webpack-plugin has added an event so we can pre-process the html tags before they
inject them. This does the work.
*/
var self = this;
function processTag(tag) {
var src = self.hwpAssetPath(util.getTagSrc(tag));
var checksum = util.getIntegrityChecksumForAsset(compilation.assets, src);
if (!checksum) {
self.warnOnce(
compilation,
'Cannot determine hash for asset \'' +
src + '\', the resource will be unprotected.');
return;
}
// Add integrity check sums

/* eslint-disable no-param-reassign */
tag.attributes.integrity = checksum;
tag.attributes.crossorigin = compilation.compiler.options.output.crossOriginLoading || 'anonymous';
/* eslint-enable no-param-reassign */
}

var processTag = this.processTag.bind(this, compilation);
pluginArgs.head.filter(util.filterTag).forEach(processTag);
pluginArgs.body.filter(util.filterTag).forEach(processTag);
callback(null, pluginArgs);
Expand Down Expand Up @@ -290,8 +301,26 @@ SubresourceIntegrityPlugin.prototype.registerJMTP = function registerJMTP(compil

SubresourceIntegrityPlugin.prototype.registerHwpHooks =
function registerHwpHooks(alterAssetTags, beforeHtmlGeneration, hwpCompilation) {
if (hwpCompilation.hooks.htmlWebpackPluginAlterAssetTags &&
hwpCompilation.hooks.htmlWebpackPluginBeforeHtmlGeneration) {
var self = this;
if (HtmlWebpackPlugin && HtmlWebpackPlugin.getHooks) {
// HtmlWebpackPlugin >= 4
HtmlWebpackPlugin.getHooks(hwpCompilation).beforeAssetTagGeneration.tapAsync(
'sri',
this.beforeHtmlGeneration.bind(this, hwpCompilation)
);

HtmlWebpackPlugin.getHooks(hwpCompilation).alterAssetTags.tapAsync(
'sri',
function cb(data, callback) {
var processTag = self.processTag.bind(self, hwpCompilation);
data.assetTags.scripts.filter(util.filterTag).forEach(processTag);
data.assetTags.styles.filter(util.filterTag).forEach(processTag);
callback(null, data);
}
);
} else if (hwpCompilation.hooks.htmlWebpackPluginAlterAssetTags &&
hwpCompilation.hooks.htmlWebpackPluginBeforeHtmlGeneration) {
// HtmlWebpackPlugin 3
hwpCompilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync('SriPlugin', alterAssetTags);
hwpCompilation.hooks.htmlWebpackPluginBeforeHtmlGeneration.tapAsync('SriPlugin', beforeHtmlGeneration);
}
Expand Down
3 changes: 2 additions & 1 deletion jmtp.js
Expand Up @@ -57,7 +57,8 @@ WebIntegrityJsonpMainTemplatePlugin.prototype.apply = function apply(
}
return (Template.asString || this.asString)([
source,
'script.integrity = sriHashes[chunkId];'
'script.integrity = sriHashes[chunkId];',
'script.crossOrigin = ' + JSON.stringify(mainTemplate.outputOptions.crossOriginLoading) + ';',
]);
}

Expand Down
1 change: 0 additions & 1 deletion package.json
Expand Up @@ -71,7 +71,6 @@
"soupselect": "^0.2.0",
"style-loader": "^0.18.0",
"tmp": "^0.0.31",
"travis-after-all": "^1.4.4",
"webpack": "^1.12.11"
},
"peerDependencies": {
Expand Down
4 changes: 3 additions & 1 deletion util.js
Expand Up @@ -118,11 +118,13 @@ function getChunkFilename(compilation, chunk) {
var args = [isInitialChunk(chunk) ? filename : chunkFilename, {
hash: compilation.hash.substr(0, compilation.mainTemplate.outputOptions.hashDigestLength),
hashWithLength: length => compilation.hash.substr(0, length),
contentHashType: "javascript",
chunk: {
id: chunk.id,
hash: chunk.hash.substr(0, compilation.mainTemplate.outputOptions.hashDigestLength),
hashWithLength: length => chunk.hash.substr(0, length),
name: chunk.name
name: chunk.name,
contentHash: chunk.contentHash
}
}];

Expand Down

0 comments on commit 1ead719

Please sign in to comment.