Guy
Guy

Reputation: 21

How to define a Content Security Policy (CSP) that utilizes 'strict-dynamic' but includes fallback to use 'unsafe-inline'?

I'm implementing the CSP header on a website that needs to dynamically load some scripts due to various reasons (mostly plugins). This is easily achieved by defining script-src using 'strict-dynamic' along with a hash/nonce for the non-dynamic scripts.

The recommendations everywhere suggest also including some high level sources/schemes and 'unsafe-inline' as fallback, in case the browser doesn't support CSPv3 and thus, doesn't support 'strict-dynamic' and dynamic loading:

script-src: 'strict-dynamic' 'sha256-somesortofhash...' https: 'unsafe-inline';

This fallback method will work fine for browsers that only support CSPv1:

But doesn't seem to work for CSPv2 browsers:

How can I define a policy with proper fallback for CSPv2 browsers as well?

Upvotes: 2

Views: 5795

Answers (2)

Jiger Jain
Jiger Jain

Reputation: 17

Your policy: script-src: 'strict-dynamic' 'sha256-somesortofhash...' https: 'unsafe-inline'; It utilizes hash and it is not well suited with strict-dynamic, I would suggest using nonce-{randomNumber} and it could solve your issues.

I would suggest checking your policy with https://csp-evaluator.withgoogle.com. It would help you with all the attributes as per the version whether they are supported with the corresponding CSP version.

And if you need more help around CSP3 you could look at this: Firefox refuses to load any scripts with strict-dynamic set

Upvotes: 1

Michele Spagnuolo
Michele Spagnuolo

Reputation: 932

'strict-dynamic' was designed mostly to work in combination with nonces. You are right - there is no perfect CSPv2 fallback when used in combination with hashes.

The uncovered case is dynamically generated inline scripts - a rare pattern, in my experience:

var s = document.createElement('script');
s.innerText = 'alert(1)';
document.body.appendChild(s);

will not work in CSPv2-compatible browsers, and the best solution in that case is to do UA sniffing and not send a policy at all.

Sourced scripts will work just fine.

On the other hand, a nonce-based policy such as:

script-src 'nonce-r4nd0m' 'strict-dynamic' 'unsafe-inline' https:

will fall-back gracefully, because for the case above you can always set a nonce manually:

var s = document.createElement('script');
s.setAttribute('nonce', 'df7Af03DRTs66pP');
s.innerText = 'alert(1)';
document.body.appendChild(s);

More about backward compatibility and fallbacks in our presentations[1][2].


[1] https://speakerdeck.com/mikispag/content-security-policy-a-successful-mess-between-hardening-and-mitigation?slide=52

[2] https://speakerdeck.com/mikispag/so-we-broke-all-csps-dot-dot-dot-you-wont-guess-what-happened-next-michele-spagnuolo-and-lukas-weichselbaum?slide=15

Upvotes: 1

Related Questions