Re: Finalizing the shape of CSP ‘unsafe-dynamic’

On Mon, Jun 6, 2016 at 5:48 PM, Mike West <mkwst@google.com> wrote:

> On Mon, Jun 6, 2016 at 4:45 PM, Devdatta Akhawe <dev.akhawe@gmail.com>
> wrote:
>>
>> Are there use-cases for these separately? I'm all for adding things to
>>> the platform if they're useful, but I'm not convinced from this thread that
>>> these keywords add anything other than complexity. That is, Brad can
>>> accomplish the things he's interested in with two policies, which I think
>>> actually turns out to be a more powerful primitive than splitting the
>>> keywords.
>>>
>>
>> hmm .. the use case I am interested in is script-src
>> https://www.dropbox.com/script/require.js 'allow-dynamic'
>>
>> Right now, this would force me to use a nonce. The nonce then is a
>> leakable token present in the HTML of the page. Not a huge risk, but still.
>>
>
> I see. That makes sense to me: you want the loader functionality, but you
> don't want the added surface area of the capability token.
>
> I think I agree that there are two orthogonal concerns here (loading an
> initial script via a nonce, hash, or URL on the one hand, and allowing that
> initial script to load other things on the other), and splitting them up
> makes sense. I worry a bit that folks would simply slap the dynamic keyword
> onto an already weak policy and call it done, but I suppose that doesn't
> make things any worse than they are today.
>

This idea (splitting unsafe-dynamic into something like 'allow-dynamic' and
'drop-whitelist'; the names are for illustrative purposes only!) is very
interesting to discuss, and I think it's a little more complicated than it
seems.

What we gain:
1. It's possible to apply CSP in places that can't or don't want to have
nonces. For example for cache-able static HTML pages we couldn't easily use
'unsafe-dynamic' because we wouldn't have the capability to load external
scripts via <script#src> -- hashes can whitelist inline scripts, but not
external ones. If we made the split, pages could combine a whitelist and
'allow-dynamic' and be safe from DOM XSS if the whitelist isn't bypassable.
2. It's easier to understand the behavior of the policy -- we decouple the
two aspects of unsafe-dynamic from each other.

What we lose:
1. Policies with 'allow-dynamic' but without 'drop-whitelist' aren't
backwards compatible and would require user-agent sniffing. That's because
any dynamically loaded scripts would be blocked in older browsers (which
don't support allow-dynamic), or they would have to be explicitly
whitelisted, resulting in an insecure policy even in new browsers. Unless
developers pay attention, it will be easier to create a policy that works
in new browsers but breaks on older ones.
2. We depart from an approach that promises easier CSP adoption and also
offers better security. If we decouple the adoption benefit (easier loading
of dynamic scripts) from the security benefit (dropping the whitelist) then
people will likely choose the adoption benefit without realizing that their
policy offers no protection against XSS -- we already know that >95% of
policies are in that boat and this is a *very* conservative estimate. I
worry that we'd abandon a big chance to improve the CSP ecosystem.
3. Arguably, having more keywords substitutes one kind of complexity
(understanding of the behavior of unsafe-dynamic) for another: there will
be more switches in CSP and realistically 'allow-dynamic' and
'drop-whitelist' would almost always have to be used together in order to
provide a security benefit.
4. (Maybe this doesn't matter as much) We introduce keywords which are
still coupled and need to be implemented simultaneously, e.g. if a
user-agent implements drop-whitelist but not allow-dynamic, pages will
break.

Based on my experience, drawbacks #1 and #2 are fairly substantial, and I'm
worried that risking them to enable the nonce-less/static content case (#1)
-- which seems to be the main benefit of the split -- could be the wrong
trade-off. Could we enable the static content case by allowing hashes to
whitelist external scripts, as Mike suggested below? This way we could
build policies without nonces so the nonce-leaking concern would disappear
(unless there's another case that I'm not thinking about?). Even absent
that, I'd generally prefer to prioritize the "dynamic application" case
where it's possible to use nonces, because this is where CSP has the
highest potential benefit against XSS.


> 'allow-dynamic' (or just 'dynamic', maybe?) and 'nonce-only'?
> 'drop-whitelist' is a little too broad, since nonces are part of the
> whitelist, and we're not dropping those. 'ignore-hosts'?
>
> Concretely, would Dropbox use one (or both?) of these keywords if we
>>> implemented them?
>>>
>>
>> Not really sure yet. But, I am inclined towards the script-src example
>> above.
>>
>
> Cool, good to hear, thanks!
>
> While we're on the topic, I'd like to harden that example via externalized
> hashes (e.g. `sha256-abc...` would allow `<script integrity="sha256-abc..."
> ...>` to load). I'd like to find a mechanism to do so in a backwards
> compatible way. We discussed it briefly at our last meeting. Anyone have
> any good ideas? :)
>

To properly discuss it, I'd suggest doing it on another thread, maybe? ;)
FWIW my preference would be to allow hashes to whitelist script URLs rather
than contents, and keep SRI as a mechanism to enforce integrity...
Otherwise, the "static content" case will be difficult to achieve with
hashes because any changes to the external scripts will break the policy,
since the digest will no longer match.

Received on Monday, 6 June 2016 17:11:10 UTC