Open arturjanc opened 3 years ago
I don't think it alone is sufficient. You'd want "COWPP"+COEP for that. Cross-origin "no-cors" subresources remain a thing to guard.
I am not sure I understand the threat that you are mentioning. Which of the WindowProxy methods that COWPP guards against is problematic in that case?
Let me add to the previous description of how COEP is sufficient, that we must key agent clusters on top-level origin as well as crossOriginIsolation status. COOP soap-plus-coep gives us that for free, buf if we did COEP or COWPP we would need to add this requirement.
I think I see what you mean. The way I see it is that reducing WindowProxy's abilities makes the agent cluster keying easier to grasp for developers. Making COEP alone change the keying also seems somewhat risky given that deploying COEP today wouldn't do that.
In that case, if the WindowPorxy policy is declarative, then I imagine that developers can deploy a policy that leaves most WindowProxy APIs in place and get crossOriginIsolation. Or do we want to restrict specific APIs? Otherwise, it is pretty much equivalent to COEP only, but doesn't surprise developers currently using COEP.
I was hoping we could have something simpler whereby we decide what is exposed and that's that. In particular during XSLeaks there was relatively strong case made for closed
and postMessage()
(presented as "COOP except for those").
I think ideally we also make this impact the frame tree in that A1 and A2 in A1 -> B -> A2 end up with their own agent cluster.
Hi everyone, apologies if this is the wrong place to ask this question, please delete/redirect me if so 🙏 .
Our product integrates with a large number of different OAuth2 IdPs, using a fairly standard popup -> our domain -> their domain -> our domain -> window.opener callback -> close-popup
flow.
We've recently encountered an oauth2 flow where the IdP is setting Cross-Opener-Origin-Policy: same-origin
, which breaks our usual flow. We've been able to mostly work around this using a BroadcastEvent fallback for now (although we're no longer able to automatically close the popup).
I've attempted to follow the thread above, but from what I can tell it mostly assumes that IdPs are driving the implementation of authentication flows, and are electing to add the COOP header once they know it'll work with their recommended flow.
If I as an 3rd-party oauth2 integration encounter a provider which sets COOP: same-origin, am I correct in thinking my options are:
This is definitely a possible approach, but practically it will mean that -- until WebID ships in most browsers -- authors of OAuth flows will have to switch to one of the workarounds like link decoration + top-level same-origin sharing of state.
This comment from above mension some workarounds, but I wasn't able to find any more details about these - have I overlooked something else in the thread?
@glenjamin those are roughly your options, yes, but please take this kind of question to Stack Overflow going forward. This is a place to discuss the HTML standard (and future proposals).
We have implemented metrics on the Chrome side to look at cross-origin proxy access and explore the various scenarios we've discussed around crossOriginIsolation and popups. The first take away from those metrics is that cross-origin accesses to WindowProxy methods are much more common within a page than from another page. The second take away is that the methods accessed are not similar when the access is coming from within the page compared to outside the page. Given this, we think that it is is best that a solution that focuses on restricting access to the WindowProxy only applies to accesses from outside the page. In terms of methods accessed, the most common ones are: closed, postMessage, opener. We think that restricting access to all WindowProxy methods but those should provide a good security guarantee while being easily deployable. Location is also accessed somewhat frequently, however I believe we do not want to allow other pages to navigate the crossOriginIsolated page.
From this we can imagine a policy. We can either define it as a version of COOP or as a new type of policy. So either we do something like:
The advantages of the first one is that it keeps all of the crossOriginIsolation enabling inside COOP. However the integration with COOP might be complicated. For example, a website could want to have a COOP of both same-origin-allow-popups and restrict-window-proxy, a combination that makes sense to defend against various xsite leaks when a website needs to open popups and cannot set COOP same-origin.
So overall, I think it would be easier to understand if we defined this as a different policy, that can also potentially enabled crossOriginIsolation. With this approach, we can have the following behavior:
As mentioned, it is possible to set a COOP on top of the Cross-Page-Window-Proxy-Policy. So for example, a page can set COOP same-origin-allow-popups, CPWPP restrict-window-proxy and COEP credentialless, in which case the browser will do a BCG switch when navigating to this page, it will be cross-origin-isolated, it will be able to open popups, however the popups will only have access to the closed/opener/postMessage WindowPorxy methods for the proxies on the page.
The interaction with COOP same-origin-plus-coep is a little bit more complex. We should probably ignore Cross-Page-Window-Proxy-Policy in that case. Otherwise, we might end up in a situation where documents in two pages have direct scripting access to each other, but are restricted when it comes to the cross-origin WindowProxy methods (if the pages are same-origin with COOP same-origin-plus-coep but have a different Cross-Page-Window-Proxy-Policy).
@arturjanc @annevk what do you think? Also, would you happen to have better naming ideas for this policy?
It might be good to set up some time to have a synchronous discussion about this. Some thoughts:
opener
is being accessed. Isn't that a field the popup itself would access?As far as naming goes, not sure. Logically it seems like an extension of the Opener Policy as it governs what the opener can do. Perhaps a couple of additional enum values is not the end of the world?
Hi Anne! Some beginning of answers below. I'm still thinking about how it all fits together and writing an explainer.
It's not clear why opener is being accessed. Isn't that a field the popup itself would access?
The only use case I could think of is window.opener.opener to get back a popup chain. Metrics are tested and I don't think this is an implementation error.
If we don't do anything for nested cross-origin documents, we continue having quite the attack surface there. Perhaps they should be configurable separately and perhaps it should not be part of v1, but I think we should sort out how it can work.
The requirements here are somewhat different because usage is massive, and because browsers don't yet all have OOPIF, and we don't need to come up with a different AgentCluster keying. We want to make something as granular as possible to avoid breakages and actually make it usable. I agree that needs attention, but we need to discuss what timeline we'd be looking at.
I don't see anything about named targeting. Say A popups B and B embeds C. And B enforces this new policy. A shouldn't be able to name target C and perhaps shouldn't be able to name target B either.
That was an issue with the original design as well and I think it makes sense to restrict it. This is similar in my opinion to what happen with window.location access. If we restrict window.location we should also restrict named targeting.
This model suggests that if A popups B and either has this policy and they are same-origin, the policy is not enforced. Is that desirable? It would mean that both windows necessarily end up in the same process and we leave the potential for parallelism on the table.
This is not the intention, and I agree that they'd need to be in different Agent Clusters to make that clean. I think that would require keying Agent Clusters by (top-level origin + Window policy + crossOriginIsolation = same or compatible page) + origin, to work without COEP. This solves interaction with COOP: Same-Origin-Plus-Coep. If two pages within a COOP:Same-Origin-Plus-Coep BrowsingContext Group have different CPWPP policies, we have the Window policy index to work with.
This introduces a LOT of keying, but I imagine restricting direct DOM access without leaning on AgentClusters would be ugly.
Do we need an additional key for agent clusters or can we delegate agent cluster lookup to the browsing context of which the top-level document has this policy? (I guess that requires a tie-in with COOP.)
As for exactly how we could implement the keying, I'd need to have a look at the spec, I have no idea.
The explainer in question: https://github.com/hemeryar/explainers/blob/main/cross_page_window_proxy_policy.md for people that want to catch up on the ongoing discussion.
Also I forgot to state that in my previous message but I agree that a synchronous meeting would probably be helpful.
Following the offline discussion, this document recapitulates the different options we've gone through so far and what are their pros and cons: https://docs.google.com/document/d/1rayFAWAIqhmcRg5hMyvMHg4QTL0f61eH4P5RaChoPHU/edit#
I still think the option presented above (alternative 3) is the more robust approach that we can extend in the long run. Alternative 4 is elegant but might be limited by itself and require the addition of another policy later on.
Thank you for putting that together so quickly!
I tend to agree that 3 or 4 is what we want to go for. I left some inline comments. I'm personally much more keen to design a single more limited alternative to cross-origin WindowProxy
than have some kind of logic in there to allow folks to choose. If we need to allow choosing I'd like to see more compelling evidence for that.
I'm also still curious about opener
. It's still hard to imagine that being relevant. Are you absolutely certain that something like parent.opener
ends up not being counted? And thus we're only discussing opener.opener
scenarios? I'd love to see some sample websites that rely on that.
One thing we still lack here is some input from web developers. What they might be able to deploy. That should be balanced with security and performance goals, but it would still be good to at least have some indication.
About the opener mystery, @ddworken had a look at the google code and mentioned this:
"Our oauth library (which tons of external sites use for login-with-google) triggers these accesses because it checks if a received message came from an opened popup by doing event.source.opener == window
"
He added metrics to see if the usage is actually coming from here. We've agreed that we can start by getting this blocked as well in the first place, and move back if it's a real issue for developers. Implementation wise it should be a simple boolean switch, and it doesn't affect the rest of the proposal.
I can provide some input from the POV of someone who has been working on large scale deployments of COOP, and is invested both in making COI easier and in improving security. From this perspective, I think there are two main bits that are worth separating:
I think #1 is great, this will make COI way easier to deploy and more broadly compatible.
For #2, supporting fine-grained restrictions seems useful to me. Some services aren't interested in COI, but would be interested in locking down attribute access (e.g. accounts.google.com which likely would be incompatible with the proposed closed-opener-postMessage
policy). In the short term, I think it makes perfect sense to focus on COI benefits and not support fine-grained restrictions. But given that there are concrete use cases for fine-grained restrictions, I think it would be a good idea to spec this in a way that enables easily adding support for fine-grained restrictions in the future (since otherwise I'm worried we'll either have a tricky deprecation or end up with two headers). Concretely: could we make it a structured header with a list of tokens that browsers parse (and currently only handle if set(tokens) == {closed,opener,postMessage}
)? This way in the future individual browsers could safely add fine-grained restrictions, and sites could start using those restrictions, without any concerns about breaking things for other browsers.
Otherwise, it all looks reasonable to me from a deployability perspective. I agree with the change relative to COWPP of having it not apply to iframes since we already have decent control over iframes (via frame-ancestors) and in a post-third-party-cookie deprecation world, iframes will be even less of a concern. As far as I understand, COOP's report-only mode gives sufficient information to roll out CPWPP which is great. It is worth noting that CPWPP has the same tricky bit as COOP of needing to be deployed atomically (so as to not block same-origin interactions during a partial rollout), but I don't see any way around this and this is a bit we're already used to dealing with for COOP, so it should be okay here too.
What I'd like to see is better justification for requests beyond closed
/postMessage
. Both of those are self-evidently useful, but beyond that it's a lot less clear and I'd rather not account for exposing them if we don't have a concrete idea why we're making that effort.
The alternatives 3 and 4 in Arthur's doc look good to me. Regarding the accessible methods on the WindowProxy, maybe we can start designing with just closed
/postMessage
being available, and if we find better evidence that opener
is needed (for example following @ddworken's investigation), we can revisit the decision not to add it.
Hi everyone, since I've drafted a first spec PR, I'd like to bikeshed the actual name of the COOP value. Some options include:
Let me know what you think, I personally like restrict-properties
I just posted https://github.com/whatwg/html/issues/7713#issuecomment-1091457683 about some further design considerations. I thought we'd use that issue going forward, but given by the comment above maybe I was mistaken? Should I repost that comment here?
Some update on the "COOP: restrict-properties" policy (let's call it that since nobody objected). The proposal for having it cause BCG swaps preserving a limited opener has been deemed undoable for reasons explained in issue #7713. The approach that is now being explored is the following:
Have a COOP: restrict-properties policy that would cause agent clusters for that page to be isolated from others. Each BrowsingContext group would have a map of <page nonce, agent cluster map>. In general, everything would be stored in the initial empty nonce map. If we start using the COOP value, each page using it gets its own agent cluster map via a new nonce.
While the behavior might seem a bit different from other COOP values at first (opener links are not restricted forever, but can be restored), it's actually not. Because we do not swap BrowsingContext groups, we're not breaking any COOP behavior, and we do not need to modify any of the fundamentals (like COOP being applied on redirects, etc). We can also reuse report-only more or less directly.
The downside would be that websites using this policy to interact with cross-origin popups would also need to rework their same-origin popup interactions to only use postMessage and closed.
We're especially interested in partner's opinion about the usability of that feature, or if the inability to communicate directly with same-origin popups would be too hard to overcome.
The explainer has been updated to reflect the latest developments: https://github.com/hemeryar/explainers/blob/main/coop_restrict_properties.md
Apologies if this is not the right place to ask this question; please redirect me if necessary.
We have been following the SharedArrayBuffer saga (https://developer.chrome.com/blog/enabling-shared-array-buffer/) in Chrome for some time, as we have a product that makes use of multiple threads in a WASM context and is thus using SAB's.
The latest update from the Chrome team (as of Dec 2021) links to this issue and seems to suggest that their temporary mitigation of allowing SAB's using their Origin Trial gate mechanism will continue until the larger issues with restrictiveness around COOP/COEP are resolved (as this issue and the explainer linked above seem to be discussing at the HTML standards level).
Since our product (and the large business it generates) relies on SAB's, we're looking for some indication from the Chrome team that SAB's will remain available via an OT beyond Chrome 103.
We have experimented with the credentialess feature and have improved some flows under COOP/COEP, but challenges still remain, including supporting browsers other than Chrome that don't have credentialess.
Since our product (and the large business it generates) relies on SAB's, we're looking for some indication from the Chrome team that SAB's will remain available via an OT beyond Chrome 103.
There is a very timely question given the Intent to Extend Origin Trial: Trial for SharedArrayBuffers in non-isolated pages on Desktop platforms from a couple of days ago, which says: We’ve received lot’s of feedback that adopting COOP/COEP is hard (details below). Therefore I’m asking for your approval to extend the SAB reverse OT again from M103 until M113 (branch point 2023-03-23)
The intent has a follow-up discussion with some concerns about pushing back the rOT deprecation by such a long time, but it seems likely that the rOT will survive for some time past the original target of M103. This is partly because the anonymous iframes proposal has yet to ship.
Incidentally, if credentiallessness and/or anonymous iframes are features that help you make your applications compatible with COOP+COEP, it could be useful to communicate it to vendors other than Chrome to give them some signal that there is indeed developer need to implement them.
FWIW, I still like the policy name popup
, but we can discuss that more once we've gotten some web developer feedback.
Update on this topic, we've reached out to a number of websites susceptible to be interested in this proposal but haven't received any feedback. I suspect this is due to the complexity of the topics involved. Our next step is to build a MVP and enable it via an origin trial, to gather more practical feedback from web developers. It would be nice if we could agree on a name before that so that we don't have to rename tons of places in the code base later on.
You mentioned you preferred COOP: popups is that still your preference? The reasoning we had with restrict-properties was that COOP: popup would hint at something that would be used for popups, whereas the main use case is for a main frame that wants both COI and to interact with popups. WDYT?
Hypothesis is interested in the login popup use case and would be interested in helping to test any solutions. I think our use case may be a little different than others. Our product is an iframed commenting app/widget (think something like Disqus) that publishers embed in their web pages, with a login flow that happens in a popup.
The restrict-properties
proposal looked like it would be adequate. One concern I do have is that we don't have control over the headers that the top-level site sends, and so it would be highly preferable if the solution didn't require changing those. We do have control over the code which loads the login popup and the headers that are sent for the iframe's HTML.
For an iframe to be crossOriginIsolated, it will unfortunately always require top level collaboration. The reason is pretty straight forward: without out of process iframe, they'll end up in the same process, so they need to somehow agree. And at this point out of process iframe is not something we can rely on as it is not supported widely enough.
I think popup
(singular as policy names usually are singular I think?) is still a reasonable name as the policy is both for popup endpoints and those making use of popup endpoints.
I could live with restrict-properties
personally, but to me it's a bit vaguer and harder to spell. Maybe @domenic, @smaug----, or @jakearchibald have thoughts that could sway this one way or another?
I slightly prefer restrict-properties
as when I'm thinking "what does this COOP policy do?" it's pretty easy to remember that restrict-properties
is the one that gives me a restricted set of properties. Whereas I think of most/all COOP values as being related to popups, so popup
doesn't really help me.
My understanding was that origin isolation was there to allow a site to exist in a process that didn't contain no-cors data (or, content that had opted in to being potentially accessed via meltdown/spectre).
Because of that, WindowProxy
is problematic, since it includes synchronous access to the DOM same-origin, and I guess sync-ish access to location
cross-origin. I didn't think it had anything to do with tracking prevention.
A developer could easily create communication between the two windows by sharing an ID in the URL, and creating a socket via the server. So it seems fine to do the same via message ports (excluding the usual things that can't travel across processes, like SAB).
I want to give popup
one more push. The way I'm thinking about it is that as a web developer, you want to answer the question "what policy do I want?". And popup
is the clearest hint we can give web developers that either want to open popups or develop popup endpoints. And then when they read up on it they can find out it'll restrict properties and prevent sharing of shared memory, even when both sides are the same origin.
FWIW I've been expecting us to apply this COOP value on the main window of applications that aren't opened in popups, but need to interact with a cross-origin popup (and which want COI so they can't use COOP: SOAP). It seems fairly awkward to use popup
in this context so something like restrict-properties
matches my mental model better.
Just a heads up, since we haven't been able to convince each other and that I've got all the docs/explainers/WPT as restrict-properties and that I'll start putting together patches soon, we'll stick to that. This can always be changed in the future but will require significant effort.
Just a note for thoughts, something that came up while working on a prototype is what we want to do with names when going to/from a COOP: RP page. Is it acceptable that a window name set by COOP: RP page is then leaked into the next non COOP: RP window? Do we want to force a name cleanup? And if we do is it going to break the regular -> COOP -> regular flow we were worried about in the first place?
Thought: make windows.name
readonly in RP mode? (I wouldn't mind hiding it entirely, e.g., returning the empty string, but that might be a bit much.)
(I still struggle to make much sense of restrict-properties
by the way. In that yes, properties are restricted, but to me it doesn't really communicate the overall idea at all.)
what's the latest status on this?
Secure popup interactions with restrict-properties
- Chrome Developers
https://developer.chrome.com/blog/coop-restrict-properties/
I have made my page cross using isolated using coop: restrict-properties & coep : credentialless. I am using msal & okta for authentication. There are certain use cases where I have to focus and close the popup window, but we can't use these methods directly instead we have to post message to these child windows via window.postMessage. But how can I add listeners to these messages on the popup/child window as I don't have control over it. Has anyone solved this issue?
The basic COOP: restrict-properties idea would be to use a single BrowsingContext group, but to increase the keying of Agent Cluster. We would have multiple same-origin documents not be able to synchronously script each other, despite being able to reach each other's Window object. Instead of increasing Agent Cluster keying, we introduce a new superset of BrowsingContext group, [...]
Could somebody provide some context on why this was done? Is this an implementation detail and the behavior should be the same as with the additional agent cluster keying?
@simon-friedberger The behavior is exactly the same as additional agent cluster keying. This is an implementation detail, but we also think that it is easier to reason about than extra keying.
@anvipul We'd like to better understand the impact on not having access to focus and close. My understanding is that you should still be able to login, though an authentication popup might be left behind. Is that correct?
@camillelamy Sometimes user may shift the focus to some other tab (with popup still open) & popup will be hidden behind the browser. Now when user comes back and click again on sign in button, either we can focus the already opened popup or close the previously opened popup and open the new one (in the latter case, we can have popup left behind even though the user has logged in).
@camillelamy, do you have any idea on how we can add event listener on the popup window which is not in our control?
@anvipul My understanding is that while the flow might still be less ideal (ie you might end up with an extra OAuth popup), the user should still be able to login.
We would really like to avoid exposing focus
and close
, as these functions are often used in popunder scenarios. We'd like to make this kind of attacks harder when targeting pages with COOP restrict-properties.
@anvipul It's not possible to add an event listener on a third party window. The whole point of COOP is to limit the ability of other websites to influence you. However, you can reach out to the owner of the window and ask them about the possibility of adding the event listener. They can then review your request and see if it makes sense for their website.
@anvipul It's not possible to add an event listener on a third party window. The whole point of COOP is to limit the ability of other websites to influence you. However, you can reach out to the owner of the window and ask them about the possibility of adding the event listener. They can then review your request and see if it makes sense for their website.
@camillelamy Reaching out to the owner is not practical. Our scenario is OIDC, and through OIDC or SAML redirects, the origin could switch to any authentication service.
You are correct in stating that the basic successful scenario should work. Our concern is that if a user navigates away during authentication, then we leave abandoned popups in the background. We know that they are there, but there is nothing that we can do about it. Our users will not know about COOP restrictions. They will just think that our application is poorly written.
Do you have any thoughts on an eventual solution to this issue?
The current model of cross-origin isolation is incompatible with federated sign-in flows based on popups. Any popup opened by a document with a COOP of
same-origin
will not be able to communicate with its opener, preventing passing information to the application to which the user wants to sign in (or, commonly, to the identity provider's iframe embedded by that application).Some background for this decision is in https://github.com/whatwg/html/issues/3740#issuecomment-417469433 and the subsequent discussion.
Based on discussions with developers, it looks like this can become a barrier to adoption of cross-origin isolation and to efforts to enforce better isolation by default. We should give developers a recommended solution for this use case which will not require them to re-architect their applications to remove cross-origin isolation from parts of their application where the user is able to sign in.
The main difficulty is that due to browsers' efforts to disable the sharing of state across storage partitions, APIs which could have potentially been used as a fallback to allow the popup to communicate with its opener (
BroadcastChannel
,localStorage
) are unlikely to be tractable approaches in the long term.A few possible alternatives:
postMessage
to be used in situations where COOP caused a browsing context group switch.localStorage
orBroadcastChannel
.I do think that something like WebID could be a good long-term solution, but I'm worried that without a short/medium-term alternative we'll make life difficult for developers; an approach like (1) or (2) above could possibly be a reasonable alternative. Given the increasing interest in cross-origin isolation it seems somewhat important for us to figure this out soon.
/cc @annevk @mikewest @camillelamy Any thoughts or other ideas here?