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

COEP and COOP inheritance for top level non-HTTP documents #6552

Open
ParisMeuleman opened this issue Apr 2, 2021 · 20 comments
Open

COEP and COOP inheritance for top level non-HTTP documents #6552

ParisMeuleman opened this issue Apr 2, 2021 · 20 comments
Labels
topic: cross-origin-embedder-policy Issues and ideas around the new "require CORP for subresource requests and frames and etc" proposal topic: cross-origin-opener-policy Issues and ideas around the new "inverse of rel=noopener" header

Comments

@ParisMeuleman
Copy link
Contributor

When creating a new browsing contexts, COOP is inherited from the opener's top level document, and COEP from the opener.
In #5198, we also clarify COOP inheritance for non-HTTP documents beyond the initial empty document. COEP inheritance for this case is not clear to me.

This inheritance seems to be problematic in the following case:

  • Main frame A, with document having COOP: same-origin, COEP: unsafe-none.
  • Iframe B embedded by A, B is same-origin with A, B specifies COEP: require-corp.
  • B opens a popup C or navigates a top level frame D to a local scheme.

According to the rules above, C's initial empty document should have COOP: same-origin and COEP: require-corp. This is problematic since an HTTP response with COOP: same-origin and COEP: require-corp would lead to a COOP value of same-origin-plus-coep.
I would suggest we adopt one of the following inheritance strategies for the initial empty document

  1. Align COEP with COOP, i.e. if COOP is same-origin we force COEP to unsafe-none. It is unclear however what we should do to COEP for COOP same-origin-allow-popups and COOP unsafe-none.
  2. Apply COOP inheritance for top frames to COEP.
  3. Open the popup noopener, no COOP/COEP will be applied. the trigger will probably be if opener’s COOP == same-origin and opener’s COEP == require-corp.
  4. Keep COOP same-origin and COEP require-corp; i.e. we accept the discrepancy in the COOP value.
  5. Update COOP to same-origin-plus-coep and open the popup in a different browsing context group. I'm not sure this is feasible (beyond using noopener).

Regarding D case, D's document (loaded from a local scheme url) should have COOP: same-origin, but COEP is unclear to me.
I suggest we apply a COEP inheritance here that matches what we decide for the initial empty document.

  1. Align COEP with COOP.
  2. Apply COOP inheritance to COEP (for top).
  3. Align COOP with COEP, i.e. update COOP to same-origin-plus-coep, this should trigger a browsing context group switch.
  4. Keep COOP same-origin and COEP require-corp, accepting the discrepancy.
  5. Keep the previous document COEP.

I am not sure what we prefer here. 4 in both scenarios seems acceptable as I think it would minimize the risk of breakages during deployment of COEP to the embedded frames. I'm just a bit worried

@ParisMeuleman ParisMeuleman added topic: cross-origin-opener-policy Issues and ideas around the new "inverse of rel=noopener" header topic: cross-origin-embedder-policy Issues and ideas around the new "require CORP for subresource requests and frames and etc" proposal labels Apr 2, 2021
@ghost
Copy link

ghost commented Apr 3, 2021

Maybe related in WICG/webpackage:
Define how CORP and COEP should work for subresource loading (#644)

@ParisMeuleman
Copy link
Contributor Author

@arturjanc @annevk I guess you'll have opinions on this.

@camillelamy @mikewest @ArthurSonzogni @antosart FYI

@annevk
Copy link
Member

annevk commented Apr 12, 2021

I recall that the idea was that COEP would only ever inherit downward and not into popups (except as part of COOP's special same-origin-plus-coep). But maybe that's only specified as far as enforcing COEP goes.

I'm not sure how reasonable that is for local schemes, but let's consider it. For blob: URLs we'd probably do want to inherit via the blob URL store. Though if B created it COOP would end up as unsafe-none I suspect? For (initial and non-initial) about:blank that seems fine. Yes, you can circumvent COEP, but that's always possible without top-level COOP involvement. For data: URLs, meh? Anything else?

@ghost

This comment has been minimized.

@annevk
Copy link
Member

annevk commented Apr 12, 2021

It's secure (or at least as secure as we know how to make it), whether it's trustworthy very much depends on your threat model and the relevant party. (It's not a great name, but this isn't the place to discuss that.)

@ParisMeuleman
Copy link
Contributor Author

I recall that the idea was that COEP would only ever inherit downward and not into popups (except as part of COOP's special same-origin-plus-coep).

IIUC you suggest that COEP is deduced from COOP special same-origin-plus-coep and defaulted for other COOP values, for relevant local schemes?

For blob: URLs we'd probably do want to inherit via the blob URL store. Though if B created it COOP would end up as unsafe-none I suspect?

Interesting, I'd have expected a similar inheritance for the blob than for the about:blank i.e. from the initiatorcreator's top level, if they are same-origin, defaulted otherwise.

For (initial and non-initial) about:blank that seems fine. Yes, you can circumvent COEP, but that's always possible without top-level COOP involvement.

I'm not sure I get the conclusion. Do you mean it is fine that about:blank inherits COOP and COEP (same-origin and require-corp) from their initiator/opener and their top? without considering altering COOP nor COEP. Or do you mean we don't inherit COEP hence the resulting document would be COOP: same-origin, COEP: unsafe-none?

For data: URLs, meh? Anything else?

👍

@annevk
Copy link
Member

annevk commented Apr 12, 2021

The idea (not sure how great it is still) is to inherit COEP downward (i.e., nested documents), but not upward/sideward (i.e., top-level documents) for relevant local schemes.

I could see inheriting COOP for blob: URLs as well. That makes sense. They're a bit special as you don't know if they are going to be nested or top-level documents.

I mean that we don't inherit COEP for about:blank (i.e., results in unsafe-none) and that it's fine.

@ParisMeuleman
Copy link
Contributor Author

ParisMeuleman commented Apr 13, 2021

If I understand you correctly, you're saying it is fine if we have a top level about:blank with COOP same-origin-plus-coep and COEP unsafe-none? I thought this document can be used by the opener (for instance) to execute/embed things.

Note that Chromium inherits here, I think Firefox does too, for instance:

main frame on https://first-party-test.glitch.me/?coep=require-corp&coop=same-origin&
execute :

a = open();
ifr = a.document.createElement("iframe");
ifr.src = "https://www.example.net";
a.document.body.appendChild(ifr);

The iframe won't load. Without COEP the iframe will load.

COOP for blob: not sure how we could do that spec wise, but I'd see something like when creating the blob we determine the COOP to be used, when navigating towards it we either use it or ignore it if it is nested (as we do for http responses actually)

@annevk
Copy link
Member

annevk commented Apr 13, 2021

No, if COOP is same-origin-plus-coep COEP should be require-corp. You do get inheritance in that case (but it's "through COOP").

@ParisMeuleman
Copy link
Contributor Author

ParisMeuleman commented Apr 13, 2021

Ok thanks for clarifying!

In my example, Chromium's behavior is wrong then (As it inherits even without COOP), I'm not sure how to interpret Firefox's, the iframe is blocked but I'm not sure due to what.

@ArthurSonzogni
Copy link
Member

If you try to deduce COEP from COOP, this will be difficult:

  • What about reporting? COOP came from the top-level document, the local-scheme document from elsewhere. If you deduce COEP from the COOP of the top-level instead of the COEP of the owner of the local-scheme document, then you will have difficulties. You can't transfer reporting endpoints from one document to another document. Inheriting this from the owner of the local-scheme document seems more natural.
  • If we add cors-or-credentialless as a possible value for COEP. Then you also have to decide whether you will set require-corp or cors-or-credentialless and whether you accept divergence in between the owner of the local-scheme document and the local-scheme document.

There are a few properties I think we want to preserve:

  1. If a top-level document has COOP == same-origin-plus-coep, then COEP != unsafe-none.
  2. When creating the initial empty document in the same browsing context group (e.g. without noopener), it inherits its capabilities to fetch from its creator. Doing something differently would be hard to implement, given this isn't part of the navigation. As a result, the initial empty document COEP must match its creator, because they have the same capability to fetch.

I realize I am only trying to find problem in previous solutions, but I am not trying to work on a solution myself. So I feel obligated to propose something. Not sure how great it will be.

The fact that COOP is somewhat tied to COEP makes things hard. I believe blocking things is easier than trying to imagine a working inheritance mechanism.

Every new document are created by a navigation, except the initial empty document. So we probably should distinguish the two:

  1. Initial empty document for popup.
    Follow the current specification. When the popup is same-origin with the top-level opener, COOP is inherited from the top-level opener. COEP is inherited from the direct opener. If COOP == same_origin && COEP != unsafe-none. Then open the popup with noopener and do not inherit anything. Alternatively you can also not open the popup.
  2. Initial empty document for iframe.
    Follow the current specification. Nothing really special.
  3. Navigation.
    Follow the current specification. Define inheritance the way you want. Maybe via PolicyContainer. No matter what happen, if you ends with COOP:same-origin and COEP != unsafe-none, I would say it is easier to cancel the navigation or commit an error document instead.

@camillelamy
Copy link
Member

I would like to avoid introducing a new case of opening a popup with rel no-opener if we can avoid it. For the case 1, I'd rather we follow COOP inheritance: i.e. inherit the top-level COEP of your page if you are same-origin with the top-level document.

@ArthurSonzogni
Copy link
Member

I would like to avoid introducing a new case of opening a popup with rel no-opener if we can avoid it. For the case 1, I'd rather we follow COOP inheritance: i.e. inherit the top-level COEP of your page if you are same-origin with the top-level document.

I would be happy not to, if there are better alternatives.

So, for the initial empty document in popup, you propose inheriting COEP from the opener's top-level document instead of the current behavior: inheriting from the opener.
This seems problematic, without noopener, the capability to fetch (e.g. URLLoaderFactory) are currently inherited from the opener. The capability to fetch is already bound with a COEP/COEP-Reporting policy. To be consistent, if you decide to inherit COEP from somewhere else, you also need to inherit the capability to fetch from the same place.
See point n°2 from my previous message in [There are a few properties I think I want to preserve].
This would be a big change. I won't be able to foresee all the consequences of this.
WDYT?

@annevk
Copy link
Member

annevk commented Apr 29, 2021

How about we inherit COEP from the creator if we determine that the COOP value is same-origin-plus-coep and otherwise we do not inherit COEP at all?

@ghost

This comment has been minimized.

@ArthurSonzogni
Copy link
Member

How about we inherit COEP from the creator if we determine that the COOP value is same-origin-plus-coep and otherwise we do not inherit COEP at all?

Is this the same as what I proposed? I believe the single difference is: In your proposition, you don't add "noopener". Is this what you meant?

The difficulty I have with not adding "noopener" is that in this case, the initial empty document inherits its capability to fetch from the creator, and this capability is already bound to a COEP policy. When setting the initial empty document's COEP, we aren't really enforcing anything new, we are just reflecting what is already in use.
What I describe is probably Chrome specific though. Going into this direction might be possible in theory, but seems difficult to me at the moment for Chrome (+ @yutakahirano FYI )

@annevk
Copy link
Member

annevk commented Apr 29, 2021

Yeah, I think so. I think it would be rather strange to force noopener because of creator's COEP.

Unless COEP is applied together with COOP, there is essentially no consistency as you could typically find another document to fetch from (at least in these same-origin scenarios).

@ArthurSonzogni
Copy link
Member

ArthurSonzogni commented Apr 29, 2021

Yeah, I think so. I think it would be rather strange to force noopener because of creator's COEP.

Yes, indeed. I agree you with you. What I proposed isn't great.


I am looking into (4) from @ParisMeuleman proposition. If we don't want "noopener", and can't inherit COEP outside of the creator for the initial empty document, then this might be a good solution.

@ParisMeuleman
Copy link
Contributor Author

regarding 4), while it seems like a reasonable option to me, I'm not sure to understand what [should] happens in the following cases:

  • Document with COOP: same-origin, COEP: require-corp navigates to document with (network) COOP: same-origin, COEP: require-corp => Probably a browsing context group switch, COOP of the new document is same-origin-plus-coep.

  • Document with COOP: same-origin, COEP: require-corp navigates to document with COOP: same-origin, COEP: none => no switch?

  • (unrelated to the option 4) itself, but related with the inheritance) Document with COOP: same-origin-plus-coep navigates to document with (network) COOP: same-origin and COEP: cors-or-credentialless.
    I guess this boils down to : what's the COOP resulting of a response with COOP: same-origin, COEP: cors-or-credentialless.
    You seem to imply Arthur that it should be same-origin-plus-coep, Is that correct? Is it really ok to have both require-corp and cors-or-credentialless in the same browsing context group? My understanding is it could be, given that cors-or-credentialless can include iframes with require-corp.

@ArthurSonzogni
Copy link
Member

regarding 4), while it seems like a reasonable option to me, I'm not sure to understand what [should] happens in the following cases:

  • Document with COOP: same-origin, COEP: require-corp navigates to document with (network) COOP: same-origin, COEP: require-corp => Probably a browsing context group switch, COOP of the new document is same-origin-plus-coep.
  • Document with COOP: same-origin, COEP: require-corp navigates to document with COOP: same-origin, COEP: none => no switch?

=> I would assume yes to both. The current specified logic about browsing context group swap applies.

  • (unrelated to the option 4) itself, but related with the inheritance) Document with COOP: same-origin-plus-coep navigates to document with (network) COOP: same-origin and COEP: cors-or-credentialless.
    I guess this boils down to : what's the COOP resulting of a response with COOP: same-origin, COEP: cors-or-credentialless.
    You seem to imply Arthur that it should be same-origin-plus-coep, Is that correct? Is it really ok to have both require-corp and cors-or-credentialless in the same browsing context group? My understanding is it could be, given that cors-or-credentialless can include iframes with require-corp.

=> Yes: same-origin-plus-coep. Tentative HTML spec here: https://whatpr.org/html/6638/origin.html#the-headers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: cross-origin-embedder-policy Issues and ideas around the new "require CORP for subresource requests and frames and etc" proposal topic: cross-origin-opener-policy Issues and ideas around the new "inverse of rel=noopener" header
Development

No branches or pull requests

4 participants