Chart.js: CSP - style-src 'unsafe-inline' should not be required

Expected Behavior

Chart.js should not depend on the the Content-Security-Policy: style-src 'unsafe-inline' directive.

Current Behavior

Chart.js adds errors to the console as the css is refused by the CSP rules

Possible Solution

Add a nonce attribute and make it possible to set the nonce. See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#Unsafe_inline_script

Steps to Reproduce (for bugs)

  1. Add Chart.js to a page
  2. Open the page with the Content-Security-Policy: style-src 'self' directive set

Context

This are the error messages:

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='), or a nonce ('nonce-...') is required to enable inline execution.
Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-OTeu7NEHDo6qutIWo0F2TmYrDhsKWCzrUgGoxxHGJ8o='), or a nonce ('nonce-...') is required to enable inline execution.

The first error occurs in platform.dom.js:308 and the 2nd in platform.dom.js:311

Environment

  • Chart.js version: 2.7.1
  • Browser name and version: Chrome Version 66.0.3334.0

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 17
  • Comments: 15 (4 by maintainers)

Commits related to this issue

Most upvoted comments

A nonce is usually a bad solution for most applications. The whole security relies on the hope that it cannot be guessed, since it doesn’t rely on the content it protects. For this to work, the nonce must at least be changed for every request, which requires to dynamically create the HTML and adds further requirements for any user. Otherwise, it is only hiding the underlying issue and creates an (in my opinion) even bigger security problem, as somebody might now trust a still insecure implementation.

A good and secure solution was already pointed out by @panuhorsmalahti, using a hash instead of a nonce and removing the CSS injection.

Going further in this direction, the extracted CSS information could be inserted into a file (lets call it chartjs.css) and be delivered together with Chart.js. A simple boolean switch could control whether the createDiv function executes el.style.cssText = style || ''; (so everything remain compatible) or not.

The switch could be set via

import Chart from 'chart.js';
Chart.useSecureCSS = true;

Lastly, adding some documentation to it, stating how to securely integrate the CSS code:

  • setting the switch to true
  • including the CSS code via <style src="chartjs/chartjs.css"></style>

as well as deprecating the default injection (so folks know only the secure way would remain after the next major release and could prepare beforehand) could complete this solution and eases the change management pressure.

+1 There is also an issue in: https://github.com/chartjs/Chart.js/blob/3fe198c86098ae50d5d5e9b74d111d5f8fa74bf0/src/platforms/platform.dom.js#L169 which injects data with hardcoded style elements when enabling responsive:true & maintainAspectRatio: false

Since the style injected is static, why not adding CSS classes and adding these class to the targeted element ? This is CSP compliant.

Hi Thanks for the response, I checked it out and it works in all browsers except MS Edge, in such browser I get:

CSP14321: Resource violated directive ‘style-src ‘self’ ‘sha256-fviu5RwuBYFcCd5CDanhy6NCLufcwvCAbm061aSqhoQ=’ ‘sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=’ ‘sha256-OTeu7NEHDo6qutIWo0F2TmYrDhsKWCzrUgGoxxHGJ8o=’ ‘sha256-wS7xf+bhXBr5EM064hQkAW0vX3ks5VoxbGn+KQC/Vhk=’ ‘sha256-cxL35Ug49Sl1zHMOdz/r0xinQ6BYGgClHdDCk2XPTzE=’’ in Content-Security-Policy: inline style, in ourUrl at line 0 column 0. Resource will be blocked.

the version of MS EDGE is 40.15063.674.0 and MS EdgeHTML is 15.15063, but I think is not the latest version.

@jrberlin you can add the hashes 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=' and 'sha256-OTeu7NEHDo6qutIWo0F2TmYrDhsKWCzrUgGoxxHGJ8o=' to the CSP header to solve the problem.

Have there been any movement on this issue? I’m happy to try my hand at a PR to fix this?