Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
melloware committed Jan 11, 2022
1 parent 259d7a0 commit 9a85153
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 5 deletions.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
This plugin was forked from the wonderful work done by [Slack](https://github.com/slackhq/csp-html-webpack-plugin) but adds some key features:

- [Subresource Integrity](http://www.w3.org/TR/SRI/) (SRI) is a security feature that enables browsers to verify that files they fetch are delivered without unexpected manipulation. Thanks to [webpack-subresource-integrity](https://www.npmjs.com/package/webpack-subresource-integrity) plugin.
- [Trusted Types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types) support and use of [DOMPurify](https://www.npmjs.com/package/dompurify) to sanitize any `innerHTML` calls to prevent XSS
- [PrimeReact](https://www.primefaces.org/primereact/) special handling for inline CSS styles. See [Issue #2423](https://github.com/primefaces/primereact/issues/2423)
- Configure NONCE for pre-loaded scripts
- Typescript definition
Expand Down Expand Up @@ -94,6 +95,7 @@ This `CspHtmlWebpackPlugin` accepts 2 params with the following structure:
- If `enabled` is set the false, it will disable generating a CSP for all instances of `HtmlWebpackPlugin` in your webpack config.
- `{boolean}` integrityEnabled - Enable or disable SHA384 [Subresource Integrity](http://www.w3.org/TR/SRI/)
- `{boolean}` primeReactEnabled - Enable or disable custom [PrimeReact](https://www.primefaces.org/primereact/) NONCE value added to the environment for inline styles.
- `{boolean}` trustedTypesEnabled - Enable or disable [Trusted Types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types) handling which automatically adds DOMPurify to sanitize `innerHTML` calls to prevent XSS
- `{string}` hashingMethod - accepts 'sha256', 'sha384', 'sha512' - your node version must also accept this hashing method.
- `{object}` hashEnabled - a `<string, boolean>` entry for which policy rules are allowed to include hashes
- `{object}` nonceEnabled - a `<string, boolean>` entry for which policy rules are allowed to include nonces
Expand All @@ -104,6 +106,39 @@ This `CspHtmlWebpackPlugin` accepts 2 params with the following structure:
- `$`: the `cheerio` object of the html file currently being processed
- `compilation`: Internal webpack object to manipulate the build

## Trusted Types

[Trusted Types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types) is a newer CSP directive which adds XSS protection by preventing `innerHTML` without being trusted.

To add Trusted Type support automatically to your application you would add the `require-trusted-types-for 'script'` CSP directive.

```javascript
{
'base-uri': "'self'",
'object-src': "'none'",
'script-src': ["'strict-dynamic'"],
'style-src': ["'self'"],
'require-trusted-types-for': ["'script'"]
};
```

If `trustedTypesEnabled=true` this plugin will automatically add a special script which executes before any other script to enable a default policy that sanitizes HTML using DOMPurify.

```javascript
import DOMPurify from 'dompurify';

if (window.trustedTypes && window.trustedTypes.createPolicy) { // Feature testing
window.trustedTypes.createPolicy('default', {
createHTML: (string) => DOMPurify.sanitize(string, {RETURN_TRUSTED_TYPE: true}),
createScriptURL: string => string, // allow scripts
createScript: string => string // allow scripts
});
};
```

You will need to include DOMPurify and Trusted Types Polyfill using `npm install dompurify trusted-types` to your `package.json`.


## Appendix

#### Default Policy:
Expand All @@ -124,6 +159,7 @@ This `CspHtmlWebpackPlugin` accepts 2 params with the following structure:
enabled: true,
integrityEnabled: true,
primeReactEnabled: true,
trustedTypesEnabled: true,
hashingMethod: 'sha384',
hashEnabled: {
'script-src': true,
Expand All @@ -149,6 +185,7 @@ new CspHtmlWebpackPlugin({
enabled: true,
integrityEnabled: true,
primeReactEnabled: true,
trustedTypesEnabled: true,
hashingMethod: 'sha384',
hashEnabled: {
'script-src': true,
Expand Down
96 changes: 92 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"dependencies": {
"cheerio": "^1.0.0-rc.5",
"lodash": "^4.17.20",
"webpack-inject-plugin": "^1.5.5",
"webpack-subresource-integrity": "^5.0.0"
},
"peerDependencies": {
Expand Down
10 changes: 9 additions & 1 deletion plugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,24 @@ declare namespace CspHtmlWebpackPlugin {
* param.
* * If `enabled` is set the false, it will disable generating a CSP for
* all instances of HtmlWebpackPlugin in your webpack config.
* @default true
*/
enabled?: boolean | ((htmlPluginData: HtmlPluginData) => boolean) | undefined;
/**
* Enable or disable SHA384 subresource integrity
* Enable or disable SHA384 subresource integrity.
* @default true
*/
integrityEnabled?: boolean | undefined;
/**
* Enable or disable custom PrimeReact NONCE value added to the environment for inline styles.
* @default true
*/
primeReactEnabled?: boolean | undefined;
/**
* Enable or disable Trusted Types default policy to sanitize innerHTML with DOMPurify.
* @default true
*/
trustedTypesEnabled?: boolean | undefined;
/**
* The hashing method. Your node version must also accept this hashing
* method.
Expand Down
19 changes: 19 additions & 0 deletions plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const isFunction = require('lodash/isFunction');
const get = require('lodash/get');
const webpack = require('webpack');
const { SubresourceIntegrityPlugin } = require('webpack-subresource-integrity');
const InjectPlugin = require('webpack-inject-plugin').default;

// Attempt to load HtmlWebpackPlugin@4
// Borrowed from https://github.com/waysact/webpack-subresource-integrity/blob/master/index.js
Expand Down Expand Up @@ -59,6 +60,7 @@ const defaultAdditionalOpts = {
enabled: true,
integrityEnabled: true,
primeReactEnabled: true,
trustedTypesEnabled: true,
hashingMethod: 'sha384',
hashEnabled: {
'script-src': true,
Expand Down Expand Up @@ -392,6 +394,23 @@ class CspHtmlWebpackPlugin {
if (this.opts.enabled && this.opts.integrityEnabled) {
new SubresourceIntegrityPlugin().apply(compiler);
}

// add default TrustedTypes policy which uses DOMPurify to sanitize HTML
if (
this.opts.enabled &&
this.opts.trustedTypesEnabled &&
this.cspPluginPolicy['require-trusted-types-for']
) {
const purifyScript = `import DOMPurify from 'dompurify';
if (window.trustedTypes && window.trustedTypes.createPolicy) { // Feature testing
window.trustedTypes.createPolicy('default', {
createHTML: (string) => DOMPurify.sanitize(string, {RETURN_TRUSTED_TYPE: true}),
createScriptURL: string => string, // allow scripts
createScript: string => string // allow scripts
});
}`;
new InjectPlugin(() => purifyScript).apply(compiler);
}
}
}

Expand Down

0 comments on commit 9a85153

Please sign in to comment.