Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 12 CSS optimization inline event handler with Content Security Policy

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.

like image 616
Alex Moss Avatar asked May 17 '21 07:05

Alex Moss


2 Answers

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
          }
        }
      }
    }
  }
},
like image 107
Michael Hubeny Avatar answered Nov 17 '22 22:11

Michael Hubeny


ATTENTION! Answer updated

UPDATED ANSWER (July 16th 2021)

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.


ORIGINAL ANSWER (June 9th 2021)

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:

  • Hash the contents of the onload handler: this.media='all'
  • Report URI has a handy tool for that: Script And Style Hasher
  • Add the hash to the script-src directive in the CSP
  • For Chrome (but not for FF), you also need to add '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
like image 30
John Hannon Avatar answered Nov 17 '22 22:11

John Hannon