After upgrading to Angular 12 my Content Security Policy blocks styles from loading correctly.
The Angular 12 devkit seems to add a new inline event handler to the CSS bundle reference in index.html, example below.
<link rel="stylesheet" href="styles.5951e4ca367b697db091.css" crossorigin="anonymous" integrity="sha384-2031E8+oC87S0N7NzRGcF8fqx777KEJOgQ3KcUN4aX6xsR3BVaV5sh4fibR5joOc" media="print" onload="this.media='all'">
Error
Refused to execute inline event handler because it violates the following Content Security Policy directive...
This seems to be related to this RFC: https://github.com/angular/angular-cli/issues/18730 but I can't find any more information about how to use it with a strict (no 'unsafe-inline') CSP.
I had the same problem after Angular 12 upgrade.
The solution for me was to set the workspace option optimization "inlineCritical" to false. The inlineCritical option was changed in Angular 12 to default true to improve First Contentful Paint, see https://angular.io/guide/workspace-config#styles-optimization-options
here is an example workspace configuration
"project": {
"architect": {
"build": {
"configurations": {
"production": {
"optimization": {
"scripts": true,
"styles": {
"minify": true,
"inlineCritical": false
},
"fonts": true
}
}
}
}
}
},
ATTENTION! Answer updated
The original solution posted below breaks Safari (MacOS) so we had to rollback and disable optimization.styles.inlineCritical
.
Also, as commented by masterfloda below, the choice should be security over performance in most if not all cases.
My original thinking was that it would be difficult to exploit (unsafe-hashes
), but I have not done a thorough InfoSec risk scoring on that.
There is a ticket open for this on the Angular repo - #20864.
I suggest you disable optimization.styles.inlineCritical
for now and like and subscribe to that issue.
Yes, this issue was introduced by Angular v12's Styles optimization options (inlineCritical: true
) which adds an onload
event handler to the link tag for the main stylesheet as follows:
<link rel="stylesheet" href="styles.<hash>.css" media="all" onload="this.media='all'">
It can be solved without disabling inlineCritical
or enabling 'unsafe-inline'
in the CSP, as follows:
onload
handler: this.media='all'
script-src
directive in the CSP'unsafe-hashes'
to the script-src
directive, otherwise it blocks with the following log in the console: Note that hashes do not apply to event handlers, style attributes and javascript: navigations unless the 'unsafe-hashes' keyword is present
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With