Detalhes do pacote

csp-rspack-plugin

rspack-contrib25MIT0.0.2

A plugin which, when combined with HtmlRspackPlugin, adds CSP tags to the HTML output

webpack, csp, sri, subresource

readme (leia-me)

CSP Rspack Plugin

[!NOTE]
This is a fork of csp-webpack-plugin, and will be used in Rspack to fix bugs and add some Rspack customized features.

License: MIT npm version NPM Downloads Build Status

About

This plugin was forked from the wonderful work done by Slack but adds some key features:

  • Subresource Integrity (SRI) is a security feature that enables browsers to verify that files they fetch are delivered without unexpected manipulation. Thanks to webpack-subresource-integrity plugin.
  • Trusted Types support and use of DOMPurify to sanitize any innerHTML calls to prevent XSS
  • PrimeReact special handling for inline CSS styles. See Issue #2423
  • Configure NONCE for pre-loaded scripts
  • Typescript definition
  • Default to SHA384 instead of SHA256
  • GitHub Actions Build and Dependabot to keep dependencies up to date

Description

This plugin will generate meta content for your Content Security Policy tag and input the correct data into your HTML template, generated by rspack.HtmlRspackPlugin or html-webpack-plugin.

All inline JS and CSS will be hashed and inserted into the policy.

Installation

Install the plugin with npm:

$ npm i --save-dev csp-rspack-plugin

Basic Usage

Include the following in your rspack config:

const { HtmlRspackPlugin } = require('@rspack/core');
const CspHtmlRspackPlugin = require('csp-rspack-plugin');

module.exports = {
  // rest of rspack config
  plugins: [
    new HtmlRspackPlugin()
    new CspHtmlRspackPlugin({
      // config here, see below
    })
  ]
}

or you can use html-webpack-plugin instead:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const CspHtmlRspackPlugin = require('csp-rspack-plugin');

module.exports = {
  // rest of webpack config

  plugins: [
    new HtmlWebpackPlugin()
    new CspHtmlRspackPlugin({
      // specific the path of html-webpack-plugin
      htmlPlugin: require.resolve('html-webpack-plugin'),
      // config here, see below
    })
  ]
}

Recommended Configuration

By default, the csp-rspack-plugin has a very lax policy. You should configure it for your needs.

A good starting policy would be the following:

new CspHtmlRspackPlugin({
  'script-src': '',
  'style-src': ''
});

Although we're configuring script-src and style-src to be blank, the CSP plugin will scan your HTML generated in rspack.HtmlRspackPlugin or html-webpack-plugin for external/inline script and style tags, and will add the appropriate hashes and nonces to your CSP policy. This configuration will also add a base-uri and object-src entry that exist in the default policy:

<meta http-equiv="Content-Security-Policy" content="
  base-uri 'self';
  object-src 'none';
  script-src 'sha256-0Tumwf1AbPDHZO4kdvXUd4c5PiHwt55hre+RDxj9O3Q='
             'nonce-hOlyTAhW5QI5p+rv9VUPZg==';
  style-src 'sha256-zfLUTOi9wwJktpDIoBZQecK4DNIVxW8Tl0cadROvQgo='
">

This configuration should work for most use cases, and will provide a strong layer of extra security.

All Configuration Options

CspHtmlRspackPlugin

This CspHtmlRspackPlugin accepts 2 params with the following structure:

  • {object} Policy (optional) - a flat object which defines your CSP policy. Valid keys and values can be found on the MDN CSP page. Values can either be a string, or an array of strings.
  • {object} Additional Options (optional) - a flat object with the optional configuration options:
    • {string} htmlPlugin - The path of html plugin, HtmlRspackPlugin by default which means using rspack.HtmlRspackPlugin
    • {boolean|Function} enabled - if false, or the function returns false, the empty CSP tag will be stripped from the html output.
      • The htmlPluginData is passed into the function as it's first param.
      • 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
    • {boolean} primeReactEnabled - Enable or disable custom PrimeReact NONCE value added to the environment for inline styles.
    • {boolean} trustedTypesEnabled - Enable or disable 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
    • {Function} processFn - allows the developer to overwrite the default method of what happens to the CSP after it has been created
      • Parameters are:
        • builtPolicy: a string containing the completed policy;
        • htmlPluginData: the HtmlRspackPlugin or HtmlWebpackPlugin object;
        • $: the cheerio object of the html file currently being processed
        • compilation: Internal rspack object to manipulate the build

Trusted Types

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.

{
  '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.

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 => sanitizeUrl(string),
        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:

{
  'base-uri': "'self'",
  'object-src': "'none'",
  'script-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"],
  'style-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"]
};

Default Additional Options:

{
  htmlPlugin: 'HtmlRspackPlugin',
  enabled: true,
  integrityEnabled: true,
  primeReactEnabled: true,
  trustedTypesEnabled: true,
  hashingMethod: 'sha384',
  hashEnabled: {
    'script-src': true,
    'style-src': true
  },
  nonceEnabled: {
    'script-src': true,
    'style-src': true
  },
  processFn: defaultProcessFn
}

Full Default Configuration:

new CspHtmlRspackPlugin({
  'base-uri': "'self'",
  'object-src': "'none'",
  'script-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"],
  'style-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"]
}, {
  htmlPlugin: 'HtmlRspackPlugin',
  enabled: true,
  integrityEnabled: true,
  primeReactEnabled: true,
  trustedTypesEnabled: true,
  hashingMethod: 'sha384',
  hashEnabled: {
    'script-src': true,
    'style-src': true
  },
  nonceEnabled: {
    'script-src': true,
    'style-src': true
  },
  processFn: defaultProcessFn  // defined in the plugin itself
})

Advanced Usage

Generating a file containing the CSP directives

Some specific directives require the CSP to be sent to the client via a response header (e.g. report-uri and report-to) You can set your own processFn callback to make this happen.

nginx

In your rspack config:

const { sources } = require('@rspack/core');
const { RawSource } = sources;

function generateNginxHeaderFile(
  builtPolicy,
  _htmlPluginData,
  _obj,
  compilation
) {
  const header =
    'add_header Content-Security-Policy "' +
    builtPolicy +
    '; report-uri /csp-report/ ";';
  compilation.emitAsset('nginx-csp-header.conf', new RawSource(header));
}

module.exports = {
  {...},
  plugins: [
    new CspHtmlRspackPlugin(
      {...}, {
      processFn: generateNginxHeaderFile
    })
  ]
};

In your nginx config:

location / {
  ...
  include /path/to/rspack/output/nginx-csp-header.conf
}

Publishing

Adjust the version in the package.json if necessary, then

npm login
# This will run npm run build automatically
npm publish --access public

Then upload code to github, create tag & release.

Contribution

Contributions are most welcome! Please see the included contributing file for more information.

License

This project is licensed under MIT. Please see the included license file for more information.