zigojacko
zigojacko

Reputation: 2063

Correctly using hash with content security policy (CSP)

I am trying to use a hash with my content security policy...

Below are two example errors in my console:

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com". Either the 'unsafe-inline' keyword, a hash ('sha256-oKmCrr+GWRARSXYeVJshOWETr0oqOtt73CNO8efpujQ='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com". Either the 'unsafe-inline' keyword, a hash ('sha256-pS4Uy3ilo+JLn8IadtJGfyO9z7jqIrGUONfEUDLxoPk='), or a nonce ('nonce-...') is required to enable inline execution.

Here is the corresponding content security policy directive:

add_header Content-Security-Policy "default-src 'self'; script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com; style-src 'self' fonts.googleapis.com; img-src 'self' cdn.shortpixel.ai secure.gravatar.com; font-src 'self' fonts.googleapis.com fonts.gstatic.com";

Specifically in this example:

script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com;

From what I gathered from reading the CSP guide on hashes, I should be able to add the hash as per my console to the directive...

The easiest way to generate it is to just open the developer tools console and it will output what the expected hash of your script was in the console error message.

But if I modify my directive to include the hash (example below), I still get the same error in console (obviously with a different hash).

script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com 'sha256-oKmCrr+GWRARSXYeVJshOWETr0oqOtt73CNO8efpujQ=';

How exactly is the correct way to hash a CSP directive? And why are there multiple errors for the same directive, is this basically one for each domain specified? Should one hash cover all the domains specified?

Not really sure how I should be doing this.

Upvotes: 5

Views: 16052

Answers (1)

granty
granty

Reputation: 8546

From what I gathered from reading the content-security-policy.com/hash/ CSP guide on hashes, I should be able to add the hash as per my console to the directive...

Yeah, it's working only "theoretically", the "practice" is more hard. Yes, Google Chrome calcs hashes, but you need to read the error message carefully to determine what is really blocked: inline script, javascript: navigation or inline event handler. Because each of these have own way how to fix.
- Inline scripts can be just allowed by 'sha256-VALUE' token.
- to allow javascript: navigation and inline event handlers you need to use 'sha256-VALUE' tokens with 'unsafe-hashes'. And not all browsers support 'unsafe-hashes' for javascript: navigation as for now.

But if I modify my directive to include the hash (example below), I still get the same error in console (obviously with a different hash).

Why do you stopped? I see you use www.googletagmanager.com (GTM), do you think GTM has only one inline script? You allowed the parent script, it began to load the child ones, so you need hashes for both.
You can use parent script hash + 'strict-dynamic' token to allow all the childs ones, but it does not work in Safari as for now.

At the final you will get a lot of hashes for all inline scripts. Bad thing is that GTM and others can time to time change content of it inline scripts, so you have to add a new hashes and to remove obsoletes. But you don't know which hash to which script belongs.

Therefore the preferable way is to use 'nonce-value' for any inline scripts, all the more since GTM distributes 'nonce' to all inline scripts except Custom HTML Tags. For Custom HTML Tags(if used) you can use hashes, because those scripts is under your control.

It's better to investigate all inline scripts manually before decide how it easier and reliable way to allow them.

PS: GTM is a hard nuts for CSP because GTM can be used to inject a open list of inline/external scripts. And if use the custom JavaScript variable names are used for the «Custom HTML tag», it required to allow 'unsafe-eval'.
You can test your GTM ID for what additional scripts it loads and which CSP is enough for it.

Upvotes: 0

Related Questions