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

COOP inheritance for popups from cross-origin iframes. #8481

Open
hemeryar opened this issue Nov 7, 2022 · 14 comments
Open

COOP inheritance for popups from cross-origin iframes. #8481

hemeryar opened this issue Nov 7, 2022 · 14 comments
Labels
topic: cross-origin-opener-policy Issues and ideas around the new "inverse of rel=noopener" header.

Comments

@hemeryar
Copy link
Member

hemeryar commented Nov 7, 2022

Hi everyone!

Currently, we do not inherit COOP for initial empty documents in popups, if they were opened by an iframe that is cross-origin with the top-level document. This is because the origin is inherited from the iframe, and COOP from the top-level frame, which would cause issues down the line.

Imagine we had page A with COOP: same-origin and an iframe B. If B opens a popup, it would inherit COOP: same-origin and origin B, in the same BrowsingContext group, which is not normally possible.

Our initial solution to this problem was to not inherit, and to set noopener if dealing with COOP: same-origin. So currently, if A sets COOP: X and an iframe B opens a popup to C:

X = unsafe-none -> This is a normal popup being opened, without COOP involved.
X = same-origin-allow-popups -> The initial empty document has origin B and COOP: unsafe-none. Navigation to C stays in the same BrowsingContext group, which is the expected behavior for same-origin-allow-popups.
X = same-origin -> We set no-opener. The initial empty document is in a separate BrowsingContext group, with origin B and COOP: unsafe-none.

This approach is not very robust, and works only with the current values. In particular the development of COOP: restrict-properties is blocked by this behavior.

What we propose instead is to group COOP in a tuple with the top-level origin that initially sent the header. Instead of comparing the document origins, we compare {value, origin} tuples of the pages COOP. This means we could always inherit COOP without security risks.

I haven't thought of a case where that wouldn't work as intended. Any feedback is welcome!

@hemeryar
Copy link
Member Author

Recording the origin also means being clear on what the origin would look like, in particular with regard to CSP sandboxing.

Today, the spec says we're supposed to block CSP sandboxing if put together with COOP. However the initial reasoning does not apply to CSP sandboxing. In Chrome's implementation, I found that we did not block CSP sandbox when used together with COOP, but that we used an opaque origin, only during the response, and not redirects.

These inconsistencies can be addressed using this proposal. The document origin would be opaque, but the COOP origin would be the actual origin. This means a page A with COOP: same-origin could navigate to a page A with COOP: same-origin and CSP: sandbox. Openers would be preserved, but DOM access would not be allowed (since one page has origin A and the other and opaque origin). Both redirects and responses would behave the same.

@hemeryar
Copy link
Member Author

@annevk for visibility

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

annevk commented Dec 21, 2022

It's not clear to me how that deals with initial about:blank which is what I thought the problem was. When you have A embeds B and B popups initial about:blank (which always happens), initial about:blank will have origin B but COOP {value, A}. I don't think we had a credible attack yet, but at that point you do have a browsing context group with two top-level documents of different origins, which violates an invariant we set for ourselves.

As for sandboxing, I think the main point around that is that when A sandboxes itself and popups A that has COOP, you don't get in a situation where you are sandboxed. COOP gives some kind of "fresh start guarantee".

@hemeryar
Copy link
Member Author

As for sandboxing, I think the main point around that is that when A sandboxes itself and popups A that has COOP, you don't get in a situation where you are sandboxed. COOP gives some kind of "fresh start guarantee".

I think we're on the same line then, as the change I mention is only for non sandboxed documents that themselves set CSP sandbox. All inheritance, be it from attribute or CSP would still lead to an error.

It's not clear to me how that deals with initial about:blank which is what I thought the problem was. When you have A embeds B and B popups initial about:blank (which always happens), initial about:blank will have origin B but COOP {value, A}. I don't think we had a credible attack yet, but at that point you do have a browsing context group with two top-level documents of different origins, which violates an invariant we set for ourselves.

In that case the invariant becomes "a browsing context group only ever has a single COOP origin". Regarding the attack vector, what this changes, is that a subframe can now have access to a main frame with the same characteristics. So we need to look at things a top-level document can do, that an iframe cannot.

One thing I thought of is Permissions Policy for crossOriginIsolated which could be trivially bypassed, as these are not inherited. Maybe it would be valuable to migrate crossOriginIsolated to a different gating, as it is bound by processes and not permissions, so it seems ill-suited.

@annevk
Copy link
Member

annevk commented Jan 6, 2023

Right, and that invariant is important as in theory the whole browsing context group can run in a single process on lower end devices.

Do you have a write-up somewhere for restrict-properties that clearly documents all the requirements? Perhaps we should consider alternative designs.

@hemeryar
Copy link
Member Author

Sorry for the loooong delay, I had to switch to another topic. I made a public doc explaining the different options and behaviors, hope that helps!
https://github.com/hemeryar/coi-with-popups/blob/main/docs/cross_origin_iframe_popup.MD

@whatwg whatwg deleted a comment from Clementhenryewona Jan 28, 2023
@hemeryar
Copy link
Member Author

hemeryar commented Feb 13, 2023

Hi @annevk, did you get a chance to look at the explainer with the different options? I'll have to get to this soon for Chrome's COOP: RP implementation :)

Thanks!

@annevk
Copy link
Member

annevk commented Feb 14, 2023

Thoughts:

  • If Chrome wants to ship this it needs a lot more work and review. If you want to experiment I'm not sure you need to block on anyone?
  • It doesn't explain the requirements or the problem. Making it hard to determine why this is the correct solution.
  • I'm not sure if I'm following what is there. The second diagram claims to "solve the confusion", but if the popup doesn't navigate, it seems we've still ended up with an undesirable situation. Essentially the problem I pointed out in my first comment above. I guess the proposed solution is that it doesn't get the cross-origin isolated capability and therefore it's okay, but that still doesn't seem great.
  • The design is really complex.
  • I still don't like the name restrict-properties. It doesn't really tell you what this is for. I think popup sells that much better.

@hemeryar
Copy link
Member Author

Thanks for the read and the feedback! I'll try to address your points:

If Chrome wants to ship this it needs a lot more work and review. If you want to experiment I'm not sure you need to block on anyone?

Sorry , it sounded more imperious than intended! We're indeed still doing the implementation for the experiment phase. Since it is somewhat independent of the rest of the COOP: RP story, I wanted to hear your opinion before committing to a couple of weeks of implementation/review.

It doesn't explain the requirements or the problem. Making it hard to determine why this is the correct solution.

I've added clear requirements in the explainer. Quickly summed up:

  • We would like not to set noopener on fresh popups, because that significantly reduces the usefulness of the COOP: rp feature.
  • We need some sort of inheritance to manage the COOP: rp opens COOP:unsafe-none. Not inheriting gives a COOP: UN -> COOP: UN no swap decision, but we want to swap.

I'm not sure if I'm following what is there. The second diagram claims to "solve the confusion", but if the popup doesn't navigate, it seems we've still ended up with an undesirable situation. Essentially the problem I pointed out in my first comment above. I guess the proposed solution is that it doesn't get the cross-origin isolated capability and therefore it's okay, but that still doesn't seem great.

You're right, we had a look at the capabilities a top-level browsing context would have compared to an iframe with a given origin. What came up was just the crossOriginIsolated permission, and we've tried to address that by having a restriction on the Permissions-Policy for those cases.

The design is really complex.

I agree to that as well, but unfortunately I don't see another path forward that doesn't significantly reduce the usefulness of the feature.

I still don't like the name restrict-properties. It doesn't really tell you what this is for. I think popup sells that much better.

I've gotten complaints from that as well internally, people would prefer allow-messaging. I'll try to organize something so that we can decide on a final name.

Thanks!
Arthur

@annevk
Copy link
Member

annevk commented Feb 14, 2023

The other thing I want to raise again while we're talking about this is that popups still present a significant privacy challenge we all have to overcome. Adding significant complexity around popups at this time seems like a risky investment.

In particular because the use cases we typically discuss are centered around logins, for which FedCM aims to be the solution. Which raises these questions:

  1. Do we have a lot of non-login use cases that warrant this?
  2. How do we imagine addressing the privacy issues for the non-login use cases?

@hemeryar
Copy link
Member Author

hemeryar commented Feb 21, 2023

Hi Anne!

  1. Do we have a lot of non-login use cases that warrant this?

Internally and externally we know about a few, on the top of my head: payments, video conferencing, data visualization, integration with embedded content (like clicking on a meeting link from an email), etc. It seems very unrealistic that we are going to be able to have individual APIs for each usage, as much as I would like to get rid of popups altogether.

  1. How do we imagine addressing the privacy issues for the non-login use cases?

We don't yet have a clear story, but we are working on it. I believe @arichiv looked at potential solutions to do communication partitioning for popups, and we'll discuss them in early April. The one we've looked at a bit is about chaining partitioning: a third-party iframe would open popups in the same partitioning, despite it being top-level.

@arichiv
Copy link

arichiv commented Apr 26, 2023

I hope to share a proposal in the next couple weeks, sorry for the delay getting back here.

@zcorpan
Copy link
Member

zcorpan commented Oct 9, 2023

Would it be possible to change the semantics of same-origin and same-origin-allow-popups to allow postMessage() and closed, if those are considered OK to allow and still keep cross-origin isolated?

@zcorpan
Copy link
Member

zcorpan commented Oct 23, 2023

What is the relationship between this and #6364 ?

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

No branches or pull requests

4 participants