Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSP3: Add something along the lines of disown-window-owner. #139

Closed
mikewest opened this issue Jan 8, 2015 · 34 comments
Closed

CSP3: Add something along the lines of disown-window-owner. #139

mikewest opened this issue Jan 8, 2015 · 34 comments
Labels
Milestone

Comments

@mikewest
Copy link
Member

mikewest commented Jan 8, 2015

@hillbrad suggested adding a disown-window-owner flag of some sort to execute https://html.spec.whatwg.org/#disowned-its-opener automagically when opening auxiliary browsing contexts. That seems reasonable, but we'll need to bikeshed the name/syntax a bit:

  1. We're not disowning the owner of this window, we're asking windows we create to disown their owners.
  2. Should this be a valueless property, or should we bundle things like this and mixed content's strict mode somehow? e.g. default-src 'self'; clever-directive-name disown-window-owner strict-mixed-content-checking?

Thread: http://lists.w3.org/Archives/Public/public-webappsec/2015Jan/0071.html

@mikewest mikewest added the CSP label Jan 8, 2015
@hillbrad
Copy link
Contributor

hillbrad commented Jan 8, 2015

Nit: the property is window.opener, so "disown-window-opener".

On Thu Jan 08 2015 at 1:05:10 AM Mike West notifications@github.com wrote:

@hillbrad https://github.com/hillbrad suggested adding a
disown-window-owner flag of some sort to execute
https://html.spec.whatwg.org/#disowned-its-opener automagically when
opening auxiliary browsing contexts. That seems reasonable, but we'll need
to bikeshed the name/syntax a bit:

  1. We're not disowning the owner of this window, we're asking windows
    we create to disown their owners.
  2. Should this be a valueless property, or should we bundle things
    like this and mixed content's strict mode somehow? e.g. default-src
    'self'; clever-directive-name disown-window-owner
    strict-mixed-content-checking?

Thread:
http://lists.w3.org/Archives/Public/public-webappsec/2015Jan/0071.html


Reply to this email directly or view it on GitHub
#139.

@mikewest mikewest added this to the CSP 3 milestone Jan 27, 2015
@cure53
Copy link

cure53 commented Mar 2, 2015

Why would this be a security-opt-in?
Wouldn't it be better to categorically destroy window.opener for any cross-origin navigation?

We currently have the problem, that browser vendors (the Chrome team) recommend to use <a rel="noreferrer"> to destroy window.opener. This is however fairly pointless as rel doesn't apply to anchors inside SVG, forms, buttons etc. - but only HTML anchors and areas.

@cure53
Copy link

cure53 commented Mar 2, 2015

And I am not even talking about MathML on Firefox yet ;)

@mikewest
Copy link
Member Author

mikewest commented Mar 2, 2015

Because everything in CSP is an opt-in. Sites rely on the current behavior of non-rel=noreferrer links (every OpenID/Single Sign On popup window you've ever seen, for instance). I don't think we can break that without an opt-in.

@cure53
Copy link

cure53 commented Mar 2, 2015

@mikewest Fair enough. Btw, I added some examples about links and link-likes that bypass rel=noreferrer: http://html5sec.org/#143

<a href="//evil.com" target="_blank" rel="noreferrer">CLICK</a> // window.opener will be null
<map><area href="//evil.com" target="_blank" rel="noreferrer">CLICK</area></map> // window.opener will be null 

<svg><a xlink:href="//evil.com" rel="noreferrer">CLICK</a></svg> // window.opener still works 
<form action="//evil.com" target="_blank" rel="noreferrer"><input type="submit"></form>// window.opener still works 
<form id="test" rel="noreferrer"></form><button formtarget="_blank" formaction="//evil.com">CLICKME</button>// window.opener still works 
<math href="//evil.com" xlink:show="new" rel="noreferrer">CLICKME</math>// window.opener still works

mikewest pushed a commit to mikewest/webappsec that referenced this issue Jun 29, 2015
Autolinking: Ignore case when procesing the 'spec' attribute.
@jeisinger
Copy link
Member

@mikewest
Copy link
Member Author

mikewest commented Oct 2, 2015

  1. We should probably implement something like that. noreferrer + _blank is a hack.
  2. The CSP directive would, I assume, apply to all navigations/windows from a page.

@jeisinger
Copy link
Member

sounds like a bug.

doesn't sound that bad: why would you submit stuff to a site but not trust it?

@jeisinger
Copy link
Member

sounds like a bug, I meant

@jakearchibald
Copy link

If my page is a non-secure context only due to the presence of window.opener, is window.opener = null enough to make my page secure?

@mikewest
Copy link
Member Author

@jakearchibald: No. The security of a context is set at the time you navigate in and we decide what IDL attributes to expose. Changing the window's opener at runtime doesn't make the context secure.

Specifics of the current implementation aside, what's the scenario you care about?

mikewest added a commit to w3c/webappsec-csp that referenced this issue Jul 25, 2016
w3c/webappsec#517 asked for this, and it's a totally reasonable thing to do.
But, w3c/webappsec#139 asked for the inverse ('disown-openee' or something),
and it's not clear to me whether there's a good syntax that might encompass
both.

Leaving both tickets open until we come up with something we're happy with.
Until then, puttign this stub in place.
@danielstjules
Copy link

danielstjules commented Jul 28, 2016

@jakearchibald

If my page is a non-secure context only due to the presence of window.opener, is window.opener = null enough to make my page secure?

Unfortunately, Safari doesn't even let you modify the opener if the child window has a different origin. From https://github.com/danielstjules/blankshield#solutions

A handful of solutions exist to prevent this sort of attack. You could:
...
Listen for the click event and prevent the default browser behavior of opening a new tab. Then, call window.open() with the href and set the the child's opener to null. Unfortunately, this does not work for Safari. Safari's cross-origin security prevents the modification of window.opener of a child window if it lies on a different origin, yet still allows the child window to access window.opener.location.

@zcorpan
Copy link
Member

zcorpan commented Dec 1, 2016

A few points:

@mikewest
Copy link
Member Author

mikewest commented Dec 1, 2016

It is argued in whatwg/html#2122 that CSP is too difficult/unpractical to implement, so making this part of CSP could hinder adoption.

The nice thing about CSP is that you don't have to implement all of it to get specific benefits. For instance, if you don't have CSP today, and all you want is to ensure that no one gets a reference to you via window.open, you could serve Content-Security-Policy: disown-opener and not bother yourself with any of the attendant complexity (assuming we decide how to spell the feature and actually ship it in a browser).

I get the general argument that CSP is complex. I don't think that the conclusion holds that creating a new mechanism would make things less complicated. :)

Nulling window.opener also prevents postMessage. What should OAuth do? See whatwg/html#2047 -- maybe a separate opt-in that makes location read-only cross-origin, but still allows postMessage?

As @annevk noted in that issue, location is never readable cross-origin. It's write-only in those circumstances.

To the broader question: authentication in a popup requires communication between the popper and the popee. disown-opener wouldn't be appropriate for such a page, as it needs to communicate. It's certainly conceivable to create more granular controls, allowing postMessage while denying opener.location = whatever. At some point that starts to feed the complexity argument you began with, but shrug. How would you suggest spelling such an option?

@mikewest
Copy link
Member Author

mikewest commented Dec 1, 2016

(@zcorpan ^^)

@zcorpan
Copy link
Member

zcorpan commented Dec 1, 2016

The nice thing about CSP is that you don't have to implement all of it to get specific benefits.

Sounds good. I wasn't sure if this was indeed the case. 🙂

As @annevk noted in that issue, location is never readable cross-origin. It's write-only in those circumstances.

Uh, yes, I mean, opt-in to disallow setting it cross-origin. As to naming/syntax, no opinion at this time.

I will note that @bzbarsky seems not so fond of the idea of introducing this sort of thing in https://lists.w3.org/Archives/Public/public-whatwg-archive/2016Dec/0005.html

@mikewest
Copy link
Member Author

mikewest commented Dec 1, 2016

I will note that @bzbarsky seems not so fond of the idea of introducing this sort of thing in https://lists.w3.org/Archives/Public/public-whatwg-archive/2016Dec/0005.html

I'm pretty sure I agree with him, but I'm open to a totally amazing idea that I haven't thought of. :)

@bzbarsky
Copy link

bzbarsky commented Dec 1, 2016

I think what I was mostly against was introducing something where you open a popup and whether that popup gets to navigate you is determined by some sort of complex dynamic algorithm.

Here's a question. If we were designing all this cross-site interaction green-field, how would it work?

One plausible answer is that the only thing allowed cross-site would be postMessage. If people think this is a reasonable thing to enable, then we could add something where a window flags itself as "https://html.spec.whatwg.org/multipage/browsers.html#crossoriginproperties-(-o-) should only return postMessage". There are problems, though. If you open a window that sets this flag, then suddenly you can't close it. On the other hand, if you open a window, arguably it shouldn't be able to close you cross-origin. So maybe my plausible answer is just wrong and we really need some sort of more complicated asymmetric setup...

Note that this is all separate from the idea of "have a way to opt in to all your window.open calls and targeted link navigations disowning openers". Or not setting them? Note that for rel=noopener we disabled targeting completely, because we couldn't figure out a sane way to make it work, but that would be a slightly odd default behavior to opt into just so you can get protection in the cases when you do open a new thing....

@zcorpan
Copy link
Member

zcorpan commented Dec 1, 2016

I think what I was mostly against was introducing something where you open a popup and whether that popup gets to navigate you is determined by some sort of complex dynamic algorithm.

OK, that's not what I had in mind.

One plausible answer is that the only thing allowed cross-site would be postMessage.

I think that would makes sense.

There are problems, though. If you open a window that sets this flag, then suddenly you can't close it.

You can postMessage to it indicating you want it to close itself. Like you can indicate you want it to navigate to somewhere.

@bzbarsky
Copy link

bzbarsky commented Dec 1, 2016

You can postMessage to it indicating you want it to close itself.

Yes, if it wants to cooperate with you....

@andypaicu
Copy link

Hello all,

I would like to re-open this discussion and see if we can get somewhere with it. It seems that the original concern can be addressed with rel=noopener and the opener is now protected from the openee.

From what I can tell the difference here is that this directive is supposed to be asymmetric and I'm not exactly sure how much that is really worth.

Is there a specific scenario that is really empowered by this directive? It seems to me that if you can't trust the window you are opening than being allowed to communicate with them one-way seems of limited use.

For now I'm quite tempted to argue that we should give this directive up entirely, perhaps focus on the inverse which (to me) seems to have more value and is more straightforward.

Thoughts?

@andypaicu
Copy link

By the "inverse" I mean this thing discussed here: w3c/webappsec-csp#194

@annevk
Copy link
Member

annevk commented Oct 9, 2017

Not having to annotate all outgoing links with rel=noopener seems like a big enough win?

@andypaicu
Copy link

@annevk Perhaps, though we would have to add a serialized-source-list to the directive (I can imagine many pages want to be selective with rel=noopener) and of course it would have to be two-way, similar to `rel-noopener'.

I could get behind a disown-opener that basically applies rel=noopener to all links not matching the serialized-source-list

@annevk
Copy link
Member

annevk commented Oct 9, 2017

I don't understand what "two-way" means here. noopener only has effect on the window being created.

@andypaicu
Copy link

Ah apologies I was under the wrong impression that noopener affects both the opener and the openee and it breaks the connection both ways.

Regardless, basically I think following the noopener behavior makes sense.

@annevk
Copy link
Member

annevk commented Oct 9, 2017

Ah, I guess you're right when it comes to window.open(), that'll return null when you pass in noopener. That isn't applicable to rel=noopener though as links never got any kind of reference to begin with. It would make sense for any kind of global CSP-based solution to apply to both.

@bzbarsky
Copy link

bzbarsky commented Oct 9, 2017

Fwiw, the "noopener" arg to window.open is totally broken in ways that make it effectively unusable in its current implementations (see whatwg/html#1902). The spec is vague enough about window.open option processing last I checked that it probably allows both that behavior and something saner, but it's not clear whether there are any plans to get that fixed on the part of browsers.... So in practice, a CSP that says "noopener all the windows we open" might be useful for sites that can get away with it. The question is how common those sites are in practice....

I do think not having to put rel=noopener on every single link causing a new browsing context, or at least not losing if you miss one, is a decent security mitigation that fits in with the general remit of CSP...

@andypaicu
Copy link

So in order to make this work we would probably needs hooks in:

https://html.spec.whatwg.org/multipage/window-object.html#window-open-steps (Step 5)
and
https://html.spec.whatwg.org/multipage/links.html#following-hyperlinks (Step 6).

We could add a should set noopener algorithm to the CSP spec that is called from the two places above with the url that is being opened and the appropriate global object. Then we check url against a serialized-source-list that is specified by this directive (whatever the name of the directive ends up being). If the url does not match then we return true.

This way you can specify urls that you want to keep the communication open or just 'none' to do basically apply noopener on any browsing contexts opened.

Perhaps a directive structure like: preserve-opener serialized-source-list which acts as a whitelist.

Does that seem reasonable? I think it covers a lot of use cases nicely and is flexible enough that it will be useful.

@baptx
Copy link

baptx commented Jun 2, 2018

Why not keep things simple and consistent by just calling the CSP directive noopener or no-opener, like it is done for the HTML attribute rel="noopener"? I found it confusing that it has not the same name. Someone else already asked this here: w3c/webappsec-csp#194 (comment)
As an example, the HTTP header equivalent to the HTML attribute rel="noreferrer" is the Referrer-Policy header with the no-referrer value: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy

@annevk
Copy link
Member

annevk commented Jun 3, 2018

Closing this in favor of w3c/webappsec-csp#194, which is the better place to discuss CSP features.

@annevk annevk closed this as completed Jun 3, 2018
@kdzwinel
Copy link

Sorry, I'm a bit confused why this was closed in favour of w3c/webappsec-csp#194 . It doesn't seem to be the same thing.

As far as I understand, three topics are being discussed here at the same time:

  1. how a website can say "I want all my links to be rel=noopener!" (so that the openee can't send me any messages)
  2. how a website can say "I want to always be opened as if rel=noopener was set on a link that opened me!" (so that the opener can't send me any messages)
  3. how the API for 1 and/or 2 should look like (CSP? separate header? apply to all or provide a mechanism to provide list of domains?)

w3c/webappsec-csp#194 seems to be discussing 2 & 3, but I'm personally interested in 1. How do I follow discussion on that?

@annevk
Copy link
Member

annevk commented Jun 20, 2018

@kdzwinel it's probably best to open a new issue for that in the linked repository.

@andypaicu
Copy link

CSP will probably not be the place to handle any of the rel=noopener functionality. I think whatwg/html#3740 looks like something that you might be interested in.

ryandel8834 added a commit to ryandel8834/WebAppSec-CSP that referenced this issue Aug 13, 2022
w3c/webappsec#517 asked for this, and it's a totally reasonable thing to do.
But, w3c/webappsec#139 asked for the inverse ('disown-openee' or something),
and it's not clear to me whether there's a good syntax that might encompass
both.

Leaving both tickets open until we come up with something we're happy with.
Until then, puttign this stub in place.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests