Breaking the `opener` relationship.

Forking this off and CCing some folks, as it's a sufficiently interesting
topic on its own.

On Wed, Apr 26, 2017 at 2:28 PM, Artur Janc <aaj@google.com> wrote:

>
>>>    - I'd love a solution to opener disownership that's generic.
>>>
>>> Can you clarify this? I don't understand.
>>
>
> Alex, the CSP3 draft has https://w3c.github.io/webappse
> c-csp/#directive-disown-opener which might be what you're looking for?
> FWIW I'd agree with the note in the spec and this bug
> <https://github.com/w3c/webappsec-csp/issues/194> that this needs some
> more deliberation.
>

As noted, I think that `disown-opener` is the wrong thing for a page to ask
for. Instead, I think something like
`block-cross-origin-access-via-windowproxy-and-etc`
is more accurate. That is, the goal isn't to prevent `window.opener` from
being set on the protected page. The goal instead is to prevent
cross-origin pages that gain a reference to the protected page (e.g. via
`window.open` or `<iframe>` in either direction) to use that reference to
poke the protected page in ways it might not expect.

Assuming that `https://a.com/sekrit` served a response with
`content-security-policy: block-cross-origin-access-via-windowproxy-and-etc`,
I'd expect the following behavior:

1.  `var x = window.open('https://a.com/sekrit')` executed from `
https://evil.com/` would return a `WindowProxy` object, just as it does
today. But, accessing `x.location` or `x.postMessage`, or any of the other
cross-origin attributes would throw a `SecurityError`.

2.  Likewise, `var x = window.open('https://evil.com/')` from `
https://a.com/sekrit` would give `https://evil.com/` a `window.opener`
handle to `https://a.com/sekrit`, but access would throw.

3.  `https://evil.com/` would be able to reach into `<iframe src="
https://a.com/sekrit">` via `frame.contentWindow` to get a `WindowProxy`,
but again we'd block access to the properties/methods.

4.  Likewise, if `https://a.com/sekrit` included `<iframe src="
https://evil.com/">`, the latter would gain a `window.top` handle to `
https://a.com/sekrit`, but access would throw.

It seems like this would be pretty straightforward to define in HTML (add a
flag to the settings object, set it via CSP's initialize steps, check it
somewhere around step 4 of
https://html.spec.whatwg.org/#windowproxy-getownproperty, throw), though I
think Chrome's implementation would be complicated. Firefox might have an
easier time of things given its architecture...

We could, I suppose, even tie this behavior to `window.opener = null` in
order to cut off access in an imperative way, if that turned out to be
desirable.

WDYT?

-mike

Received on Thursday, 27 April 2017 10:58:19 UTC