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

Restrict when MessagePort's onclose event can fire #10201

Open
fergald opened this issue Mar 14, 2024 · 12 comments
Open

Restrict when MessagePort's onclose event can fire #10201

fergald opened this issue Mar 14, 2024 · 12 comments
Labels
security/privacy There are security or privacy implications topic: serialize and transfer

Comments

@fergald
Copy link

fergald commented Mar 14, 2024

What is the issue with the HTML Standard?

As described here security concerns mean that Chrome will not implement onclose as specced. TL;DR it bakes into the standard a signal that garbage collection has occurred in the holder of the other end of the port.

Suggestion from @asutherland:

How about opt-in but same-origin is automatically opted in? Because ports can be infinitely re-shipped this might be most sanely modeled as a new flag "has been shipped cross-origin". The flag gets set when entangling based on the environment, so once a port goes across origins it's now opt-in even if it's subsequently re-shipped to its original origin.

@fergald
Copy link
Author

fergald commented Mar 14, 2024

@asutherland Same-origin is defnitely safe. I'm not sure how much same-origin MessagePort usage there is since same-origin has more direct methods available.

I wonder if we could also fire it

  • when the port is explicitly closed
  • some kind of opt-in
  • when the receiver has no handler

So then at least we would cover

  • you've written a receiver library that does the right thing by opting in
  • you've sent your port but the window has navigated to something unexpected

"no handler" also potentially leaks some info. Unclear to me if that would also be considered a problem.

@annevk
Copy link
Member

annevk commented Mar 14, 2024

What's Chrome's solution for it all being observable through Web Locks as well? At least when the close event was added the premise was that it could be emulated. Is that not the case?

@annevk annevk added topic: serialize and transfer security/privacy There are security or privacy implications labels Mar 14, 2024
@fergald
Copy link
Author

fergald commented Mar 14, 2024

@annevk I'm not familiar with that. Since WebLocks are per-origin, I don't see how it leaks information cross-origin (which is Chrome Security's concern).

As for emulation, yes, I believe this demo demonstrates that this information is already pretty readily available. However, the concern was about explictly baking it in. I would argue that the difference is slight but then maybe that's why I'm not on the security team...

@annevk
Copy link
Member

annevk commented Mar 14, 2024

But that demo can be defeated by tying the lifetime of MessagePort objects to the global, right? That's something we should probably do. I think the question is if there's a possibility of observing this absent that.

@fergald
Copy link
Author

fergald commented Mar 15, 2024

I'm not sure what you mean by defeated. Perhaps you're trying the demo in Safari which GCs aggressively. The demo does quite different things in different browsers.

  • In Chrome, the outcome is that no GC occurs until the the other window is closed or navigates to a different URL.
  • In Safari, the WeakRef become null almost immediately because www.example.com has no message listener, so the port is GCed quickly. So Safari already leaks that there is no listener (unclear if anyone is concerned by this).
  • In Firefox, the WeakRef never becomes null because FF intentionally never collects it to avoid leaking this info.

So in Safari, tying the port to the global would keep it alive, presumably until navigation but that is exactly Chrome Security's concern.

I don't think there's a great resolution to his that preserves the current spec, unless someone has a good argument why leaking this GC (which may or may not coincide with navigation) doesn't really matter.

@annevk
Copy link
Member

annevk commented Mar 15, 2024

I mean that we should align on the Gecko model.

@fergald
Copy link
Author

fergald commented Mar 18, 2024

It should be possible to provide a service over MessagePort, across domains, with a decent chance of avoid leaks. So it should be possible opt-in to sending close on document destruction. I've seens suggestions that just using the port or adding a listener to it is enough of a signal or it come be more explicit like port.closeOnDestroy = true.

@fergald
Copy link
Author

fergald commented May 10, 2024

@annevk To be clear, you are proposing that we spec that MessagePorts should be leaked and not GCed when they are cross-site? If we do that are OK with collecting them when they have had a listener added?

@annevk
Copy link
Member

annevk commented May 13, 2024

If by "leaked" you mean tied to the lifetime of the relevant global, sure. I don't really understand your second question as there's a grammar error. If you meant to write "are you OK" I don't understand why adding a listener would make them more collectable. It seems that would make them less collectable, but I'm probably missing something.

@fergald
Copy link
Author

fergald commented May 15, 2024

The intention is to find circumstances where the port can be disentangled without an explicit close. There have been a couple of suggestions

usage

  • b.com sends a port to a.com
  • a.com adds a listener to it or does postMessage
  • a.com's document is destroyed
  • the port is disentangled and b.com can learn that a.com has been destroyed

opt-in

Add a boolean attribute like notifyOnClose. If it's set to true, then the close event will fire. It's reset to false every time the port is transferred.

@annevk
Copy link
Member

annevk commented May 16, 2024

Looking at this again I wonder how Firefox defeats the attack. I was misunderstanding something initially. What does Firefox never collect? Maybe @asutherland can help out here.

I think an opt-in makes sense. I do wonder about the OP's suggestion of having different defaults for same and cross-origin. That is kinda counter to treating message passing as a capability-based mechanism as it's written to be in the specification. (With a notable exception for window.postMessage().)

@asutherland
Copy link

Looking at this again I wonder how Firefox defeats the attack. I was misunderstanding something initially. What does Firefox never collect? Maybe @asutherland can help out here.

In Firefox, all shipped MessagePorts go through our IPC. When our IPC layer is processing the implicit close for the collected port:

Honestly, it's not clear this behavior was entirely intentional (we will certainly spew NS_WARNINGs in the parent process when this case happens if the closed port sends us messages); the code has a bunch of technical debt and is due for a cleanup. But I think I might have avoided changing the behavior in a few bugs because it seemed like it might have been equally been intentional to avoid leaking GC, but it's hard to tell because our infrastructure makes it hard to find old discussion of things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
security/privacy There are security or privacy implications topic: serialize and transfer
Development

No branches or pull requests

3 participants