@@ -39,8 +39,8 @@ class CspHtmlWebpackPlugin {
39
39
*/
40
40
constructor ( policy = { } , additionalOpts = { } ) {
41
41
// the policy we want to use
42
- this . policy = Object . assign ( { } , defaultPolicy , policy ) ;
43
- this . userPolicy = policy ;
42
+ this . policy = Object . freeze ( Object . assign ( { } , defaultPolicy , policy ) ) ;
43
+ this . userPolicy = Object . freeze ( policy ) ;
44
44
45
45
// the additional options that this plugin allows
46
46
this . opts = Object . assign ( { } , defaultAdditionalOpts , additionalOpts ) ;
@@ -63,15 +63,17 @@ class CspHtmlWebpackPlugin {
63
63
htmlPluginData ,
64
64
'plugin.options.disableCspPlugin'
65
65
) ;
66
-
67
66
if ( disableCspPlugin && disableCspPlugin === true ) {
67
+ // the HtmlWebpackPlugin instance has disabled the plugin
68
68
return false ;
69
69
}
70
70
71
71
if ( isFunction ( this . opts . enabled ) ) {
72
+ // run the function to check if the plugin has been disabled
72
73
return this . opts . enabled ( htmlPluginData ) ;
73
74
}
74
75
76
+ // otherwise assume it's a boolean
75
77
return this . opts . enabled ;
76
78
}
77
79
@@ -94,25 +96,25 @@ class CspHtmlWebpackPlugin {
94
96
* @param {object } $ - the Cheerio instance
95
97
* @param {string } policyName - one of 'script-src' and 'style-src'
96
98
* @param {string } selector - a Cheerio selector string for getting the hashable elements for this policy
97
- * @param {object } policyObj - the working CSP policy object
98
- * @param {object } userPolicyObj - the sanitized CSP policy object provided by the user
99
99
* @return {object } the new policy for `policyName`
100
100
*/
101
- createPolicyObj ( $ , policyName , selector , policyObj , userPolicyObj ) {
102
- // Wrapped in flatten([]) to handle both when policy is a string and an array
103
- const flattenedUserPolicy = flatten ( userPolicyObj [ policyName ] ) ;
101
+ createPolicyObj ( $ , policyName , selector ) {
104
102
if (
105
103
this . opts . devAllowUnsafe === true &&
106
- ( flattenedUserPolicy . includes ( "'unsafe-inline'" ) ||
107
- flattenedUserPolicy . includes ( "'unsafe-eval'" ) )
104
+ this . userPolicy [ policyName ] &&
105
+ ( this . userPolicy [ policyName ] . includes ( "'unsafe-inline'" ) ||
106
+ this . userPolicy [ policyName ] . includes ( "'unsafe-eval'" ) )
108
107
) {
109
- return userPolicyObj [ policyName ] ;
108
+ // the user has allowed us to override unsafe-*, and we found unsafe-* in their defined policy. Let's use it
109
+ return this . userPolicy [ policyName ] ;
110
110
}
111
111
112
+ // otherwise hash all of the elements passed in
112
113
const hashes = $ ( selector )
113
114
. map ( ( i , element ) => this . hash ( $ ( element ) . html ( ) ) )
114
115
. get ( ) ;
115
- return flatten ( [ policyObj [ policyName ] ] ) . concat ( hashes ) ;
116
+
117
+ return flatten ( [ this . policy [ policyName ] ] ) . concat ( hashes ) ;
116
118
}
117
119
118
120
/**
@@ -163,30 +165,24 @@ class CspHtmlWebpackPlugin {
163
165
metaTag . prependTo ( $ ( 'head' ) ) ;
164
166
}
165
167
166
- const policyObj = JSON . parse ( JSON . stringify ( this . policy ) ) ;
167
- const parsedUserPolicy = JSON . parse ( JSON . stringify ( this . userPolicy ) ) ;
168
-
169
- // If the user policy contains 'unsafe-inline' for either script-src or style-src, we need to
170
- // avoid hashing the existing script tags, so as to avoid implicitly disabling the
171
- // 'unsafe-inline' preference.
172
-
173
- policyObj [ 'script-src' ] = this . createPolicyObj (
168
+ // looks for script and style rules to hash
169
+ const scriptRule = this . createPolicyObj (
174
170
$ ,
175
171
'script-src' ,
176
- 'script:not([src])' ,
177
- policyObj ,
178
- parsedUserPolicy
172
+ 'script:not([src])'
179
173
) ;
180
- policyObj [ 'style-src' ] = this . createPolicyObj (
181
- $ ,
182
- 'style-src' ,
183
- 'style:not([href])' ,
184
- policyObj ,
185
- parsedUserPolicy
174
+ const styleRule = this . createPolicyObj ( $ , 'style-src' , 'style:not([href])' ) ;
175
+
176
+ // build the policy into the context attr of the csp meta tag
177
+ metaTag . attr (
178
+ 'content' ,
179
+ this . buildPolicy ( {
180
+ ...this . policy ,
181
+ 'script-src' : scriptRule ,
182
+ 'style-src' : styleRule
183
+ } )
186
184
) ;
187
185
188
- metaTag . attr ( 'content' , this . buildPolicy ( policyObj ) ) ;
189
-
190
186
// eslint-disable-next-line no-param-reassign
191
187
htmlPluginData . html = $ . html ( ) ;
192
188
0 commit comments