Helmet.js / Express Content Security Policy errors with Angular ngCspNonce

130 Views Asked by At

Edit:
FYI, my problem this was probably caused by PrimeNG, the component framework i was using. There are various CSP related issues with the library.
I ended up not using the nonces, but using SSRI hashes (by compiling the Angular files using the --subresource-integrity flag.
Then I calculating the hashes with ssri, and passed that to Helmet.

Can anyone help me with a Content Security Policy configuration issue?
I'm setting up a new Angular v17 project, hosted through a ExpressJS backend on Google Cloud AppEngine.

Unfortunately I keep getting errors like:
Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' 'nonce-TESTNONCE123abc'". Either the 'unsafe-inline' keyword, a hash ('sha256-iKJahwY4ryjjFnDI8Iu0CVhTGbf2E5wqHhIzgODvwh8='), or a nonce ('nonce-...') is required to enable inline execution. Note that hashes do not apply to event handlers, style attributes and javascript: navigations unless the 'unsafe-hashes' keyword is present. errors

The Backend
I'm using HelmetJS to set the headers, and want to do it with a nonce.
(for debugging I'm always giving the same hardcoded nonce TESTNONCE123abc, but I'll generate a proper one for each request)

app.use(helmet(
        <HelmetOptions>{
            contentSecurityPolicy: <any>{
                directives: {
                    defaultSrc: ["'self'"],
                    scriptSrc: [
                        "'self'",
                        "'nonce-TESTNONCE123abc'",
                        "'unsafe-inline'"
                    ],
                    styleSrc: [
                        "'self'",
                        "'nonce-TESTNONCE123abc'",
                    ],
                    fontSrc: [
                        "'self'"
                    ],
                }
            }
        }
    )
)

In the browser, I see the headers being set succesfully:

Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-TESTNONCE123abc' 'unsafe-inline';
style-src 'self' 'nonce-TESTNONCE123abc';
font-src 'self';
base-uri 'self';
form-action 'self';
frame-ancestors 'self';
img-src 'self' data:;
object-src 'none';
script-src-attr 'none';
upgrade-insecure-requests

Which https://csp-evaluator.withgoogle.com/ thinks is pretty good!
The only 'medium severity finding' is script-src 'self' can be problematic if you host JSONP, Angular or user uploaded files.
But otherwise than that, all green checkmarks!

The frontend. The primeng index.html file has this line: <app-root ngCspNonce="##CSP_NONCE##">

when building the frontend, you see that placeholder nonce is used for the inline styles & scripts. like <style nonce="##CSP_NONCE##"> and <script nonce="##CSP_NONCE##">

The placeholder ##CSP_NONCE## then gets replaced with the nonce in my express route, by TESTNONCE123abc. Successfull replacement

The other relevant piece of configuration might be my angular configuration:

angular.json -> projects.app.architect.build.options:

...
"assets": [
  "src/favicon.ico",
  "src/assets",
  {
    "glob": "**/*",
    "input": "src/assets/fonts/",
    "output": "/fonts/"
  }
],
"styles": [
    "src/styles.scss"
]
...

and angular.json -> projects.app.architect.build.configurations.production:

...
"optimization": {
  "scripts": true,
  "styles": {
  "minify": true,
  "inlineCritical": true
},
"fonts": true
},
"outputHashing": "all"
...

And as far as I can figure out, that should all be fine... but why am I still getting errors then?.

0

There are 0 best solutions below