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

Pop-up Tracking Protection #7

Open
jackfrankland opened this issue Feb 13, 2020 · 19 comments
Open

Pop-up Tracking Protection #7

jackfrankland opened this issue Feb 13, 2020 · 19 comments
Labels
interest: webkit Implementer interest from WebKit (e.g. Apple/Safari, Igalia/GNOME Web) needs implementer interest Proposals cannot become work items without multi-implementer interest

Comments

@jackfrankland
Copy link

Bringing over from the comment here: #6 (comment), and to fit with the guidelines of this repository, offering a proposal to prevent it.

Pop-up tracking

Third parties are able to gain access to first-party storage using the following method:

  1. The content publisher's page embeds a third-party script from tracker.example.
  2. The third-party script tries to read third-party cookies for tracker.example.
  3. If it can't, it injects a tracker.example iframe on the publisher's page.
  4. User clicks on content in the iframe (intentionally or via click-jacking).
  5. Using window.open, a new tab/window is opened for tracker.example.
  6. tracker.example window is now first party and can read or write cookies.
  7. tracker.example window accesses a function on tracker.example iframe, via window.opener, to pass an identifier.
  8. tracker.example window closes itself.
  9. Identifier can be passed to initial third-party script via postMessage and stored in first-party storage for continued tracking on the site.

The pop-up needs only to be open for a very short amount of time. However, this method can still be used by third parties that the user wishes to interact with, in a less covert manner, but without their express wish to be tracked.

Proposal

On the condition that a third-party iframe uses window.open (or anchor with target not "_top") without the "noopener" feature to open a new browser tab or window, the resulting window, when navigated to the same third-party domain as the iframe, should be considered to be running in a third-party context for the sake of storage.

Because having full script access to the window.opener is the offending article, the new window will no longer be able to break the barrier between the first-party and third-party contexts.

This will not affect pop-ups that were opened by a first-party, or opened with the "noopener" feature.

Considerations

  • Would this affect oAuth implementations?
  • Should this only affect "known trackers"?
  • Should this be implemented only with the existence of an alternative method of gaining access to first-party storage (i.e. Storage Access API), either within the iframe or the pop-up.
@othermaciej
Copy link

I endorse working on this.

@jackfrankland
Copy link
Author

I have come to the (now pretty obvious) realisation that there is a more straight-forward way for third parties to gain access to their first party storage via a popup:

  1. Third-party tracker.example script opens a new window/tab, navigating to tracker.example page.
  2. tracker.example pop-up is now first-party, and can access its first-party storage.
  3. tracker.example pop-up uses window.opener.postMessage to send an identifier back to an event listener in the original tracker.example script.

The proposal in its current state is limited to pop-ups that have been opened by third-party iframes. It could be changed to: Any pop-up that has window.opener access is treated as third-party when navigated to a domain not considered same-site to the top window of the opener. It would essentially be treated the same as an iframe.

The effect that I see this would have on oAuth, depending on how the browser treats third-parties, is that an existing logged-in session would not be able to be read, and the user would be required to enter their credentials. A developer could choose to open the window with the "noopener" feature instead, but then may not be able to detect when the oAuth process has completed as easily.

@hober
Copy link
Member

hober commented Feb 19, 2020

Would you like time on the next call to talk about this proposal?

@jackfrankland
Copy link
Author

If there’s interest, then yes, happy to.

@hober hober added the agenda+ Request to add this issue to the agenda of our next telcon or F2F label Feb 20, 2020
@jameshartig
Copy link

As I mentioned on the call we utilize window.opener from a popup to handle subscriptions. I can share a live example if that helps, but what happens is:

  1. Publisher installs our third-party tag
  2. Non-subscriber sees modal to subscribe to publisher
  3. Popup opened to Admiral's domain
  4. After successful charge (or login to existing subscription), we use window.opener to send back a successful subscription to the original page to close the modal.

I think the proposal of requiring interaction would reduce breakage for us in the current process since we would only use window.opener after the user has either logged-in or entered their credit card.

I've internally proposed switching this to generating a first-party-isolated "session" on the original page that we will then send to the popup via the URL and then that "session" is used for the subscription. When the popup is closed the original page can make a third-party call to determine if subscription was successful. We would then be able to use the noopener feature in this case. We could still detect when the window was closed via window.closed on the window object returned from window.open.

@hober hober removed the agenda+ Request to add this issue to the agenda of our next telcon or F2F label Feb 27, 2020
@jackfrankland
Copy link
Author

@fastest963
I appreciate that partitioning the storage to the opener's first-party would affect your current behaviour - this is very similar to the way we handle sessions for our third-party content at the company I work for.

In an oAuth flow at log-in/grant stage, first-party storage access could be requested via the Storage Access API, if the window was opened without the noopener feature, just like an iframe.

Your flow is a little bit different to oAuth though I believe. Currently, WebKit does allow access to first-party storage to a third-party script, on the condition that the user has visited the site and a cookie is set (which can be done using the pop-up). They have stated that this compatibility feature will be removed at some point in time (the Storage Access API is there to act as the method of gaining access). You may have been aware, but I mention it in case it will affect your internal proposal.

@hober
Copy link
Member

hober commented Mar 10, 2020

Would anyone like to talk about this on this week's telcon? If so, please add the agenda+ label. (If you can't, let me know and I can add it.)

@jameshartig
Copy link

jameshartig commented Mar 18, 2020

Currently, WebKit does allow access to first-party storage to a third-party script, on the condition that the user has visited the site and a cookie is set (which can be done using the pop-up). They have stated that this compatibility feature will be removed at some point in time (the Storage Access API is there to act as the method of gaining access).

@jackfrankland can you elaborate? You mean a third-party script can't access document.cookie or do you mean the third-party HTTP request does not include credentials? Or did you mean a third-party iframe can't access it's first-party cookies inside of the iframe without using Storage Access API?

@jackfrankland
Copy link
Author

@fastest963 sorry, it was badly worded. I meant that the third-party HTTP request will not include credentials when made from the first-party, or from its third-party iframe.

@jameshartig
Copy link

@jackfrankland no worries, I appreciate the clarification and that's what I had assumed you meant. That should be sufficient for our implementation.

@hober hober added needs implementer interest Proposals cannot become work items without multi-implementer interest interest: webkit Implementer interest from WebKit (e.g. Apple/Safari, Igalia/GNOME Web) labels Mar 31, 2020
@hober
Copy link
Member

hober commented Mar 14, 2022

@jameshartig @jackfrankland any interest in pursuing this further? @jyasskin @pes10k, perhaps this should be merged into nav tracking mitigations?

@johannhof
Copy link
Member

This was discussed again recently at the Feb 10 CG meeting as part of storage partitioning. Per my understanding and if I'm reading the minutes correctly there was rough consensus that we should try partitioning popups.

It might make more sense to track this as part of Storage Partitioning or keep it as a separate item. I'm not sure if it's best placed in nav tracking.

cc @annevk @krgovind @miketaylr

@johannhof
Copy link
Member

@pes10k
Copy link

pes10k commented Mar 15, 2022

+1 from me on the above, this seems closer to storage-partitioning than navigation tracking

@TanviHacks
Copy link
Member

@annevk Do you want this discussion to be part of the cookie ad hoc, or discussed separately as part of a regular teleconference?
privacycg/meetings#16

@annevk
Copy link

annevk commented Mar 22, 2022

I think this would be best discussed separately.

@jasonnutter
Copy link

I have come to the (now pretty obvious) realisation that there is a more straight-forward way for third parties to gain access to their first party storage via a popup:

  1. Third-party tracker.example script opens a new window/tab, navigating to tracker.example page.
  2. tracker.example pop-up is now first-party, and can access its first-party storage.
  3. tracker.example pop-up uses window.opener.postMessage to send an identifier back to an event listener in the original tracker.example script.

The proposal in its current state is limited to pop-ups that have been opened by third-party iframes. It could be changed to: Any pop-up that has window.opener access is treated as third-party when navigated to a domain not considered same-site to the top window of the opener. It would essentially be treated the same as an iframe.

The effect that I see this would have on oAuth, depending on how the browser treats third-parties, is that an existing logged-in session would not be able to be read, and the user would be required to enter their credentials. A developer could choose to open the window with the "noopener" feature instead, but then may not be able to detect when the oAuth process has completed as easily.

I work on an OAuth JS SDK, and can confirm that partitioning storage for sites that are in "third-party" popups (relative to their opener) would break popup-based interactive authentication flows (i.e. the user would need to relogin in each popup), as we assume the popup is in a first-party context and thus has access to cookies that were set when the user first logged in at the top frame.

When the opener is the top frame, this in theory can be mitigated by invoking a full-page redirect (like if the user has popups blocked), but is still unfortunate for applications that desire to not have the user leave their site to complete the interactive request.

When the opener is inside an iframe, this may not be able to be mitigated programmatically (i.e. the user would be forced to relogin in the popup), as the IDP will likely not allow their login UX to be rendered in an iframe (i.e. the SDK can't perform a redirect inside the iframe to show the login UX).

I could see first-party sets being a way to restore existing behavior for openers that are in the same site as our IDP (i.e. our own products), but that would mean our customers would not be able to use popup-based interaction (which is a popular feature).

@samuelgoto
Copy link

samuelgoto commented Mar 28, 2022

I could see first-party sets being a way to restore existing behavior for openers that are in the same site as our IDP (i.e. our own products), but that would mean our customers would not be able to use popup-based interaction (which is a popular feature).

In addition to first-party sets, for cross-party popups, FedCM can help the browser observe this as a federated/oauth login flow and avoid the intervention after the user acknowledges.

@arichiv
Copy link

arichiv commented Sep 7, 2023

https://arichiv.github.io/opener-storage-partitioning/ is a recent proposal on blink-dev for one approach to this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interest: webkit Implementer interest from WebKit (e.g. Apple/Safari, Igalia/GNOME Web) needs implementer interest Proposals cannot become work items without multi-implementer interest