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

Add unsafe-inherit as a value for the Cross-Origin Opener Policy #4581

Closed
arturjanc opened this issue Apr 29, 2019 · 15 comments
Closed

Add unsafe-inherit as a value for the Cross-Origin Opener Policy #4581

arturjanc opened this issue Apr 29, 2019 · 15 comments
Labels
addition/proposal New features or enhancements security/privacy There are security or privacy implications topic: cross-origin-opener-policy Issues and ideas around the new "inverse of rel=noopener" header

Comments

@arturjanc
Copy link

arturjanc commented Apr 29, 2019

The problem
While working on a COOP deployment strategy across our apps we came across a potential issue which might be common enough to warrant supporting at the spec level. The situation is as follows:

  1. An origin deploys Cross-Origin-Opener-Policy: same-origin for all of its responses.
  2. The developer notices breakage because one of the documents in the origin was being used in an auxiliary context by a cross-origin document and COOP prevents the interaction. This poses a problem because:
  • The developer cannot keep setting COOP for the affected document because it will prevent legitimate cross-origin interactions.
  • The developer cannot remove COOP from the affected document because it will put it in a different browsing context group from the rest of its own origin, preventing same-origin interactions; the rest of the origin will have COOP and will be in a different browsing context group.
  1. As a result, the rollout of COOP would likely have to be rolled back until the developer can make sure that no document in the origin is being used cross-site.

It seems useful for developers to be able to exempt parts of their site from COOP enforcement to enable incremental rollouts.

A possible solution
I believe we could solve this by adding a new value of unsafe-inherit to COOP. When a document sets Cross-Origin-Opener-Policy: unsafe-inherit it would elect to be put into the browsing context group of the opening document, assuming the opening document's own COOP doesn't prevent this.

That is:

  • If a document without COOP opens a popup which sets COOP: unsafe-inherit then the popup would end up in its browsing context group and the documents can communicate.
  • If a document with COOP opens a popup which sets COOP: unsafe-inherit, then:
    • If the popup is same-origin / same-site with the opener and the COOP of the opener is same-origin / same-site, the documents would be in the same browsing context group.
    • If the popup is cross-origin then it will be in the same browsing context group if and only if the opener specifies unsafe-allow-outgoing.

This would allow sites like OAuth providers set COOP: unsafe-inherit on documents which need to be accessible by cross-origin windows while using a stricter COOP elsewhere in the same origin/site.

Similarly to CORP this could also provide a path to setting COOP restrictions by default sometime in the future by allowing developers with resources which need to be accessed cross-origin with a way to opt out of the restrictions.

Note: The original text of this issue referred to this mode as cross-origin instead of unsafe-inherit and references to cross-origin still remain in some of the discussion below.

@mikewest @annevk @empijei @csreis @lweichselbaum

@annevk annevk added addition/proposal New features or enhancements security/privacy There are security or privacy implications labels Apr 29, 2019
@annevk
Copy link
Member

annevk commented Apr 29, 2019

Overall this makes sense, but I wonder if this would require other nuanced changes. E.g., currently same-site in one COOP and same-origin in another constitute a non-match (irrespective of their hosts). This would put more strain on where the COOP comes from as it's now quite important which you use for comparison purposes. In turn, this would complicate testing further as well.

@annevk annevk added the topic: cross-origin-opener-policy Issues and ideas around the new "inverse of rel=noopener" header label May 13, 2019
@annevk
Copy link
Member

annevk commented May 14, 2019

Thinking about this some more, I wonder if instead we can make this a different keyword from cross-origin: unsafe-inherit or some such. This keyword signifies that you take over the COOP of whoever initially created the browsing context group you are being pulled into. I think this would avoid all the model changes a keyword such as cross-origin implies.

@empijei
Copy link

empijei commented May 16, 2019

Minor nit: since we already have unsafe-allow-outgoing, why not call this unsafe-allow-incoming?

This would, in fact, allow openees to be opened in someone else's context, which is the reciprocal action of allowing yourself to bring someone else in your context (u-a-o).

@annevk
Copy link
Member

annevk commented May 16, 2019

I think the one problem with that is that this is not only unsafe-allow-incoming, since outgoing is inherited as well, right? If A sets same-origin unsafe-allow-outgoing and loads B which sets unsafe-allow-incoming, B gets to open whatever.

@annevk
Copy link
Member

annevk commented May 28, 2019

One issue @mystor raised that is good to keep in mind is that this proposal requires remembering the final computed state in session history. That is, in

  1. example.com A with policy same-origin popups example.com B with policy unsafe-inherit.
  2. Assert: B's final computed policy is same-origin.
  3. The user closes A and navigates B to elsewhere.example with policy does not matter.
  4. The user now presses back.
  5. Assert: B's final computed policy is same-origin.

it would be bad if 5 was not true I think.

@arturjanc
Copy link
Author

unsafe-inherit or something like that sounds quite reasonable to me, as does the requirement to restore the computed state of COOP upon B/F navigations. 

Thinking about this even more, I wonder if we could make 'unsafe-inherit' the default mode, i.e. have the lack of a COOP header imply the behavior we're talking about here (keeping the browsing context for same-origin / same-site navigations depending on the COOP value of the opener page).

A negative consequence of this model is that there would be "action at a distance", i.e. a page could exhibit different behavior depending on whether the user arrived on it from a page with COOP or not. Requiring developers to explicitly set unsafe-inherit could also be more auditable and allow developers to find all documents in their apps that opt themselves into this mode.

The upside is that this seems easier to deploy -- not setting COOP on some documents would still result in expected behavior, i.e. same-origin navigations/popups which open that document would retain the existing browsing context group, rather than creating a new one. It also seems to not poke holes in the security model because all navigations outside of the scope defined in the original COOP (same-origin or same-site) would result in a new browsing group. The one exception is if the original page sets COOP with unsafe-allow-outgoing, which would now make cross-site links from same-origin-no-COOP pages open in the same browsing context, but this seems like a minor issue (and we could make unsafe-allow-outgoing not inherit if need be).

Do you have any thoughts about this @annevk?

@annevk
Copy link
Member

annevk commented Jun 7, 2019

I would like to understand your final example better:

  • I have a document with same-origin unsafe-allow-outgoing.
  • A same origin popup is opened from there without a policy.
  • Thus we'd inherit the policy, right? It's now same-origin unsafe-allow-outgoing.
  • We then navigate the popup cross-site.

How would this not replace the popup browsing context?

@arturjanc
Copy link
Author

In your example, if we open a second popup from the document with the inherited COOP, then that popup will be in the same browsing context group because of unsafe-allow-outgoing, right?

So, previously, if some parts of your origin set COOP with unsafe-allow-outgoing, the of risk putting a cross-origin document in the same browsing context group would be limited to only documents which explicitly set the header. In the inherit-by-default world that risk expands to same-origin documents which don't set COOP, because their popups will remain in their context group.

I have to say that I'm skeptical about this being a meaningful security risk, because it applies only in cases where an application uses unsafe-allow-outgoing, doesn't set COOP origin-wide, and allows COOP-less documents to open cross-site popups. Even then, an attacker would have to convince the user to have a series of interactions with the site that would result in opening a popup to an attacker-controlled site. If this overall model sounds reasonable, then my guess is that a spec note about this concern could be sufficient...

@annevk
Copy link
Member

annevk commented Jun 9, 2019

It will be in the same browsing context group, but that would also happen without inheritance (because then the unsafe popup would lack a policy). So I don't think that's a novel angle? Also, if a victim resource does not set COOP, an attacker could also open it into a popup or (unless protected) a frame (see also XSLeaks).

@arturjanc
Copy link
Author

You're right, the concern I described for unsafe-allow-outgoing is not any different from the status quo; I forgot that unsafe-allow-outgoing already assumes trust in navigations from your popups.

I think there is still an issue with inheritance, but it's different:

  1. I have a sensitive page with COOP same-origin and open a same-origin popup without COOP.
  2. The popup has an iframe that could be controlled by an attacker (e.g. it allows sanitized HTML with frames or has an ad).
  3. The iframe now has access to the page with COOP via top.opener

Previously, the popup would be in a different browsing context group because of a same-origin navigation to a no-COOP document. With inheritance, the same-origin popup will be put in the same browsing context group and its frame will get access to the opener.

It's hard to say how realistic this is (the scenario seems somewhat contrived), so the main question is whether the adoption benefits would outweigh this concern.

@annevk
Copy link
Member

annevk commented Jun 14, 2019

I think I agree that implicit copying of the policy is probably better. We can add another value (e.g., strict) in the future that'd avoid that kind of thing, if desired. It's potentially weird that with this model same-origin and same-site are a non-match, but probably okay? (I could see that if you pull same-site into same-origin it becomes same-origin, but not sure how great that is and it still leaves all the other cases as non-matches.)

@annevk
Copy link
Member

annevk commented Jun 27, 2019

What we did not explicitly consider is that inheriting by default might give complications if a document is unsure about its "outgoing" links. That is, if A1 adopts COOP and A2 does not and A2 needs to load B in a popup and A1 sometimes loads A2 in a popup, it depends on whether or not A1 specifies unsafe-allow-outgoing whether A2 is going to function.

So therefore, explicit inheritance might be better:

  • same-origin / same-site; sure about incoming and outgoing links
  • the above followed by unsafe-allow-outgoing; sure about incoming, unsure about outgoing links
  • unsafe-inherit; unsure about incoming, sure about outgoing

A variant not in the above table is the combination of unsafe-inherit and unsafe-allow-outgoing. It's not clear to me there's any benefit to that, but you might end up with that if whoever opened you had unsafe-allow-outgoing set (or lacked COOP).

@annevk annevk changed the title Add cross-origin as a value for the Cross-Origin Opener Policy Add unsafe-inherit as a value for the Cross-Origin Opener Policy Jul 1, 2019
@annevk
Copy link
Member

annevk commented Jul 5, 2019

The COOP processing model has support for unsafe-inherit now and the interaction with COEP is defined as well.

@mystor
Copy link
Contributor

mystor commented Jul 15, 2019

Back in #4581 (comment) @annevk mentions a conversaion with me which relates to session history. I think my mind might have changed on what behaviour we should take there. I originally thought we needed to store the inherited COOP state inside of session history, so that when going back in history it would act the same. This would be needed to make the behaviour when the document is in the BFCache match the behaviour when it is not better.

I'm not convinced that this is the right decision, given that the behaviour of loading something out of history is already poorly defined, and can be quite different depending on what has happened, including history being truncated, surviving across browser restarts, and being evicted from the cache. It seems like it might be much simpler to not store this information, and consider loads from history to, if the document isn't bfcached, be effectively a new fetch from the network, inheriting from the new context it is loading in.

I'm not super attached to this, but I'm not sure that storing this extra information in session history is worthwhile, especially considering how underspecified history is right now. 🤷‍♀️

@annevk
Copy link
Member

annevk commented Oct 28, 2019

Given that this is already in the test suite and part of the processing model I'm going to close this, but see #5044 for some follow-up work regarding this feature.

@annevk annevk closed this as completed Oct 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements security/privacy There are security or privacy implications topic: cross-origin-opener-policy Issues and ideas around the new "inverse of rel=noopener" header
Development

No branches or pull requests

4 participants