Files
cellxgene/client/configuration/webpack/cspHashPlugin.js
Bruce Martin 55ef1448e8 CSP content hashes (#1406)
* remove duplicate content-type header

* plumbing to compute CSP content hashes

* add logging of missing CSP hashes

* convert sub-class init protocol to static

* factor function

* lint
2020-04-17 11:42:09 -07:00

51 lines
1.3 KiB
JavaScript

const cheerio = require("cheerio");
const crypto = require("crypto");
HtmlWebpackPlugin = require("html-webpack-plugin");
class CspHashPlugin {
constructor(opts) {
this.opts = { ...opts };
}
apply(compiler) {
compiler.hooks.compilation.tap("CspHashPlugin", (compilation) => {
HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
"CspHashPlugin",
(data, cb) => {
const { filename } = this.opts;
if (filename) {
const $ = cheerio.load(data.html, { decodeEntities: false });
const results = {};
results["script-hashes"] = $("script:not([src])")
.map((i, elmt) => this.digest($(elmt).html()))
.get();
results["style-hashes"] = $("style:not([href])")
.map((i, elmt) => this.digest($(elmt).html()))
.get();
const json = JSON.stringify(results);
compilation.assets[filename] = {
source: () => json,
size: () => json.length,
};
}
// Tell webpack to move on
cb(null, data);
}
);
});
}
digest(str) {
const hash = crypto
.createHash("sha256")
.update(str, "utf8")
.digest("base64");
return "sha256-" + hash;
}
}
module.exports = CspHashPlugin;