-
Notifications
You must be signed in to change notification settings - Fork 0
/
inline-script-csp-html-webpack-plugin.js
68 lines (59 loc) · 2.64 KB
/
inline-script-csp-html-webpack-plugin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
const cheerio = require('cheerio');
const CspHtmlWebpackPlugin = require('csp-html-webpack-plugin');
const flatten = require('lodash/flatten');
const get = require('lodash/get');
/**
* InlineScriptCspHtmlWebpackPlugin
* An extension of CspHtmlWebpackPlugin to handle Content Security Policies (CSPs).
* This class only modifies a single property (`_useHtmlParser2`) in the Cheerio configuration
* to customize how HTML is parsed.
*/
class InlineScriptCspHtmlWebpackPlugin extends CspHtmlWebpackPlugin {
/**
* Constructor
* Calls the base class constructor to set up the plugin with user-defined or default policies and options.
* @param {object} policy - CSP policy object, typically defining 'script-src' and 'style-src'.
* @param {object} additionalOpts - Additional options for nonce/hash generation and processing.
*/
constructor(policy = {}, additionalOpts = {}) {
super(policy, additionalOpts);
}
/**
* Processes HtmlWebpackPlugin's HTML output to inject the Content Security Policy.
* The key difference from the base class is setting `_useHtmlParser2: false` in the Cheerio configuration.
* @param {object} compilation - Webpack's compilation object.
* @param {object} htmlPluginData - Data object from HtmlWebpackPlugin containing the generated HTML.
* @param {function} compileCb - Callback to continue Webpack's compilation process.
*/
processCsp(compilation, htmlPluginData, compileCb) {
const $ = cheerio.load(htmlPluginData.html, {
decodeEntities: false,
_useHtmlParser2: false, // *** Changed from 'true' in the base class to 'false' ***
xmlMode: get(htmlPluginData, 'plugin.options.xhtml', false),
});
// if not enabled, remove the empty tag
if (!this.isEnabled(htmlPluginData)) {
return compileCb(null, htmlPluginData);
}
// get all nonces for script and style tags
const scriptNonce = this.setNonce($, 'script-src', 'script[src]');
const styleNonce = this.setNonce($, 'style-src', 'link[rel="stylesheet"]');
// get all shas for script and style tags
const scriptShas = this.getShas($, 'script-src', 'script:not([src])');
const styleShas = this.getShas($, 'style-src', 'style:not([href])');
const builtPolicy = this.buildPolicy({
...this.policy,
'script-src': flatten([this.policy['script-src']]).concat(
scriptShas,
scriptNonce
),
'style-src': flatten([this.policy['style-src']]).concat(
styleShas,
styleNonce
),
});
this.processFn(builtPolicy, htmlPluginData, $, compilation);
return compileCb(null, htmlPluginData);
}
}
module.exports = InlineScriptCspHtmlWebpackPlugin;