Re: Making it easier to deploy CSP.

As a quick update, we are currently testing 'unsafe-dynamic' on a few
user-facing sites, including

The relevant bits of the policy are:
Content-Security-Policy: script-src 'unsafe-inline' 'nonce-..' 'unsafe-dynamic'; object-src 'none';

On the main application change was to add the `nonce'
attribute to trusted external scripts, e.g.
<script src="" nonce="..."></script>

The ReCAPTCHA API loads additional external sub-scripts, and
'unsafe-dynamic' allows them to execute. This has two main benefits for the
1. It facilitates creating a policy for users of most JS APIs -- the site
owner doesn't have to figure out the locations of all JS sub-resources
loaded by each API, as long the top-level script is trusted and given a CSP
nonce. It also reduces the potential for breakage if paths of sub-scripts
ever change.
2. It makes for a stricter policy. With 'unsafe-dynamic', dangerous
resources in whitelisted domains [1,2] are no longer a problem because
trust is now based on the presence of a nonce and the whitelist is ignored.

With a policy like the one above, browsers which support CSP, but don't
support nonces will allow scripts to execute based on 'unsafe-inline' and
the source whitelist. Browsers which support nonces but don't support
unsafe-dynamic will ignore 'unsafe-inline' and will rely on the nonce and
the whitelist. Browsers which support unsafe-dynamic will rely solely on
the nonce and will transitively trust dynamically created scripts, and will
additionally ignore the whitelist.

Based on what we have seen so far this appears to be a fairly promising
approach and we will experiment with it in larger applications in the near



On Fri, Feb 12, 2016 at 2:56 PM, Mike West <> wrote:

> Hello, lovely webappsecians!
> I've been talking to Google's security folks about their adventures in
> deploying CSP to Google products. The TL;DR is that they're scared of
> whitelists (because of all the legacy junk on `` and `
>`), and are frustrated with loading widgets and libraries
> whose content they don't control. They love (cryptographic) nonces and
> hashes, and have a small proposal for a new source expression which would
> make deployment at Google (and hopefully elsewhere) easier.
> # Whitelists
> As it turns out, `` and other origins we depend on are full of
> terrible endpoints that allow user-injected script (see `
> for example). We mitigate this risk with extensive `script-src` directives
> full of deep paths, which is brittle, awkward, and sometimes impossible
> (because some folks dynamically generate all the things!). It's also
> vulnerable to open redirects stripping the path, and of course sprawling
> origins like ours have open redirects too. Huzzah for legacy!
> The security team here would be thrilled if they could use (cryptographic)
> nonces and hashes for everything instead of relying on whitelists.
> But:
> # Dynamic Content
> Widgets and libraries make this dream difficult, as they insist on loading
> code from various places, and don't do a good job explaining what code
> they'll actually need before doing so (I'm looking at you, Google Maps). We
> can certainly add all of these paths to the whitelists as well, but they
> change on a somewhat regular basis, and end up with the same drawbacks as
> noted above.
> As it turns out, in the presence of a (cryptographic) nonce, this is
> something that the library itself could deal with, by grabbing the token
> from somewhere on the page, and using it when injecting its own script. The
> token is implicitly a script-execution capability:
> ```
> var ce = document.createElement;
> window.nonce =
> document.querySelector('script[nonce]').getAttribute('nonce');
> document.createElement = function (e) {
>  var el = ce.apply(this, arguments);
>  el.setAttribute('nonce', window.nonce);
>  return el;
> };
> ```
> While we work on updating every library in the entire world to use this
> pattern, we're also experimenting with getting the browser to do the
> busywork for us, in a backwards compatible way:
> # 'unsafe-dynamic'
> We're proposing a new `'unsafe-dynamic'` source expression which has the
> following effects when added to the `script-src` directive:
> 1.  If neither a hash nor a nonce is present in the directive's source
> list, do nothing. Otherwise:
> 2.  Ignore all `scheme-source` and `host-source`source expressions, as
> well as `'unsafe-inline'`. This gives us backwards compatibility, and
> ensures that developers who opt-into this mechanism won't leave themselves
> open to whitelist-based vulnerabilities; if you use 'unsafe-dynamic',
> that's all you use. That is, given the policy: `script-src 'unsafe-inline'
> 'nonce-abcdef' 'unsafe-dynamic'`, Safari would see
> `script-src 'unsafe-inline'` <>
> (as it doesn't support nonces, while supporting browsers would see
> `script-src 'nonce-abcdef' 'unsafe-dynamic'`.
> 3.  Skip CSP enforcement on script execution for `<script>` elements which
> are not "parser-inserted". This basically boils down to automatically
> applying the capability noted above for scripts inserted via something like
> `appendChild(createElement('script'))`. We're only focusing on
> non-parser-inserted scripts, as (anecdotally) `document.write` and
> `innerHTML` are significantly more likely to contribute to XSS than
> `appendChild`. Moreover, `appendChild` accounts for the large majority of
> intentionally inserted scripts, based on an analysis of several dozen
> popular origins.
> You can play with most of this in Chrome Canary (behind
> chrome://flags/#enable-experimental-web-platform-features). Based on some
> experimentation with a crazy nonce-injecting extension, a policy like
> `'unsafe-eval' 'nonce-abcdef' 'unsafe-dynamic'` allows strict whitelisting
> with very little breakage on various Google properties and a few other high
> profile sites. The folks I've CC'd have more details on those tests for
> y'all if you're interested.
> I'll write up a patch to CSP to spell this out in more detail, but I hope
> the overview here is enough to get some early feedback. :)
> -mike

Received on Sunday, 27 March 2016 07:18:21 UTC