Chart.js should not depend on the the Content-Security-Policy: style-src 'unsafe-inline' directive.
Chart.js adds errors to the console as the css is refused by the CSP rules
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
Content-Security-Policy: style-src 'self' directive set
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
I confirm the bug,
2.6 is not affected
We are having the same issue after upgrading to 2.7.1, is there any workaround to fix this without disabling/changing our current CSP policy ?
Thank you !!
Julian
@jrberlin you can add the hashes 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=' and 'sha256-OTeu7NEHDo6qutIWo0F2TmYrDhsKWCzrUgGoxxHGJ8o=' to the CSP header to solve the problem.
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.
Any news on this?
+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.
+1
I confirm, in v2.7.2, there are conflicts with 'self' Content Security Policy and the following lines:
https://github.com/chartjs/Chart.js/blob/0963c8f76c997643aa3aa1101c34ea31cb58eab2/src/platforms/platform.dom.js#L196
https://github.com/chartjs/Chart.js/blob/0963c8f76c997643aa3aa1101c34ea31cb58eab2/src/platforms/platform.dom.js#L308
https://github.com/chartjs/Chart.js/blob/0963c8f76c997643aa3aa1101c34ea31cb58eab2/src/platforms/platform.dom.js#L311
Hi, this is sort of blocking me from releasing https://tonic.technology — I'd be happy to make a PR. Possible fixes for the issues that @smariel points out could be...
After the element is rendered, querySelect it and add the style with JS (that will pass CSP).
For the head element, we need to set an attribute (either nonce or integrity on the programatically created style element (either could be passed in as a config option to the constructor.
This would be solved by solving the second issue.
Have there been any movement on this issue? I'm happy to try my hand at a PR to fix this?
I fixed this by
style-src 'self' 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=' 'sha256-OTeu7NEHDo6qutIWo0F2TmYrDhsKWCzrUgGoxxHGJ8o=';.chartjs-size-monitor,
.chartjs-size-monitor-expand,
.chartjs-size-monitor-shrink {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
pointer-events: none;
visibility: hidden;
z-index: -1;
}
.chartjs-size-monitor-expand > div {
position: absolute;
width: 1000000px;
height: 1000000px;
left: 0;
top: 0;
}
.chartjs-size-monitor-shrink > div {
position: absolute;
width: 200%;
height: 200%;
left: 0;
top: 0;
}
This works at least on latest Firefox and Chrome.
Add a nonce attribute and make it possible to set the nonce
For the head element, we need to set an attribute (either nonce or integrity on the programatically created style element (either could be passed in as a config option to the constructor.
@fxOne @hxoht what would be your approach to implement this solution? Can you write a small snippet showing how it would work in HTML / Javascript? (I'm not familiar with CSP so don't fully get how it's supposed to be configured).
Could someone who reported CSP errors be able to build PR #5952 and confirm that it solves this issue?
I am not familiar with github and building a project, so I'm not sure I did the right thing...
In #5952, clicked on commits then on <> to browse the repo. I cloned it and built it following the instructions. Then I put the chart.js folder in my node_modules, in place of the "official", to keep the same context.
Keeping unsafe-inline, chart.js works well.
But if I remove this policy, I still have a violiation in platform.dom.js:312:
https://github.com/chartjs/Chart.js/blob/7cd3961387412c4801096053af24bb64e3b263ab/src/platforms/platform.dom.js#L312
And I also have the following error at line 316:
Uncaught TypeError: Cannot read property 'insertRule' of null
https://github.com/chartjs/Chart.js/blob/7cd3961387412c4801096053af24bb64e3b263ab/src/platforms/platform.dom.js#L316
Thanks @smariel, you did it right, and that confirms #5952 doesn't fix the CSP issue.
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:
true<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.
Most helpful comment
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 thecreateDivfunction executesel.style.cssText = style || '';(so everything remain compatible) or not.The switch could be set via
Lastly, adding some documentation to it, stating how to securely integrate the CSS code:
true<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.