w3c / webappsec-csp

WebAppSec Content Security Policy
https://w3c.github.io/webappsec-csp/
Other
210 stars 78 forks source link

'strict-dynamic' should not be bound to only nonces/hashes #309

Open april opened 6 years ago

april commented 6 years ago

(refiling from https://github.com/w3c/webappsec/issues/534)

It makes complete sense why 'strict-dynamic' is defined the way it is, to make it backwards compatible with CSP2 and CSP1. However, at some point in the glorious future, every browser will support 'strict-dynamic'. This means that every page on a domain that wants to use 'strict-dynamic' will be bound to include inline JavaScript.

My proposal is this: allow some way to use 'strict-dynamic' with a host-source. You should be able to do this:

script-src 'strict-dynamic' https://example.com/loader.js

Or maybe this:

script-src 'strict-dynamic /loader.js'

And have all your script loading shim be neatly contained inside a single file. Ideally this would be combined with the ability to specific paths only in a host-source (such as by doing 'self'/loader.js), but it need not be.

I would love to use 'strict-dynamic' on my static, templated site but the current design of CSP3 makes it fairly difficult to do so. Because it is static, I can't use nonce-source. And while I could use hash source, that would require me to change my CSP HTTP header fairly constantly and calculate the hash of a piece of inline script, which is somewhat cumbersome to do. If I could simply specify the path to a single JavaScript shim, I could have all the benefits of 'strict-dynamic' without the baggage that comes with managing a hash-source.

arturjanc commented 6 years ago

It's not entirely a solution to the problem you outlined, but one workaround that we've been fairly happy with for our static sites is to use a loading shim as an inline <script> which defines an array with the URLs of all external scripts, and then dynamically loads them (foo = createElement('script') ... document.head.appendChild(foo)). You can then whitelist the inline script via its CSP3 hash -- if the names of scripts don't change frequently, you don't have to update the hash as often (even if the contents of the scripts are updated).

I imagine that Mike might not be particularly excited to add complexity to 'strict-dynamic', which is hard to understand as it is, so maybe the approach above is a reasonable middle ground in some cases?