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

Probably don't allow interception of navigations from other documents #75

Closed
domenic opened this issue Mar 15, 2021 · 5 comments · Fixed by #80
Closed

Probably don't allow interception of navigations from other documents #75

domenic opened this issue Mar 15, 2021 · 5 comments · Fixed by #80
Labels
foundational Foundational open questions whose resolution may change the model dramatically

Comments

@domenic
Copy link
Collaborator

domenic commented Mar 15, 2021

Chrome implementation folks are concerned about the security implications of exposing the navigated-to URL in cases like:

  • window.open(url, nameOfSomeWindow)
  • <form target="nameOfSomeWindow">
  • window['nameOfSomeWindow'].location.href = ...

As noted in the explainer,

Note that today it is not possible to intercept cases where other frames or windows programatically navigate your frame, e.g. via window.open(url, name), or history.back() happening in a subframe. So, firing the navigate event and allowing interception in such cases represents a new capability. We believe this is OK, but will report back after some implementation experience.

The case for intercepting these was never super-strong, so we should probably start restricting them. It's not clear to me yet whether we should always restrict them, or only restrict them when cross-origin.

Similarly, currently we fire a cancelable but non-respondWith-able navigate event for history.back() navigates which cause you to move cross-document. This is slightly hard to implement, and is inconsistent with how we don't fire such an event for browser UI back/forward. It was done because of my general tendency toward "fire navigate in as many cases as possible". But probably we should reconsider. Especially since I think it could get you into weird states if only one frame cancels a back navigation. Moving to a new issue.

If you're a web developer and would be very sad about these sorts of restrictions on navigation interception, please let us know. I'm hopeful that these are edge cases that don't need navigate event support.

@domenic domenic added the foundational Foundational open questions whose resolution may change the model dramatically label Mar 15, 2021
@domenic
Copy link
Collaborator Author

domenic commented Mar 16, 2021

I started working on this and realized there are several options. From most-restrictive to least restrictive:

  1. Do not fire navigate when the initiator frame is different from the navigated frame. (In the spec, when the source browsing context is not equal to the navigated browsing context.)

  2. Do not fire navigate when the initiator frame is cross-origin-domain from the navigated frame. (The reasoning being that if they are same-origin-domain, then they have sync access to each other anyway so I don't see much gain.)

  3. Do not fire navigate if both: the initiator frame is different from the navigated frame, and the destination URL is cross-origin to the navigated frame's current URL.

  4. Do not fire navigate if both: the initiator frame is cross-origin-domain from the navigated frame, and the destination URL is cross-origin to the navigated frame's current URL.

Thoughts appreciated, @csreis @natechapin and any others. My instinct is to lean toward least-restrictive.

@csreis
Copy link

csreis commented Mar 17, 2021

If we have to allow it in some cases, then I can see the argument for cases where the initiator frame is same-origin. (I'm unclear what same-origin-domain refers to; is that same-origin after taking any modifications of document.domain into account, or is it same-site?)

I don't think the decision should take the destination URL into account. If a cross-origin initiator frame is targeting this frame, this frame should have no ability to observe or intercept it, even if the destination URL is for this frame's current origin. This seems problematic in principle (since the initiator origin's actions shouldn't be affected by another origin's scripts), but it could also have security consequences for things like Sec-Fetch-Site. For example, the server may have XS-Leaks defenses that prevent responding to a query when initiated by other origins, but option 4 would bypass the server and potentially carry out the query locally.

Thus, I would suggest option 2. (Or option 1, since it's always easier to relax a restriction if needed than to add one later.)

@domenic
Copy link
Collaborator Author

domenic commented Mar 17, 2021

I'm unclear what same-origin-domain refers to; is that same-origin after taking any modifications of document.domain into account, or is it same-site?

The former; basically, they're same-origin-domain iff they can currently synchronously reach each other, potentially via document.domain shenanigans.

Thanks for narrowing things down! Either option (1) or (2) seem reasonable to me, and I'll think harder about whether we should start restrictive or start more lenient.

@domenic
Copy link
Collaborator Author

domenic commented Mar 18, 2021

To modify the above: I think we should always fire navigate for same-document cases (i.e. fragment navigations), even if they come from a different document. This is equivalent to watching for hashchange today, and seems important so that other pages cannot cause the target document to lose track of where it is in terms of history, while still having all its existing JS state.

In other words, you should only be able to non-interceptably navigate a document to a new document; you should not be able to non-interceptable navigate a document to a fragment.

domenic added a commit that referenced this issue Mar 18, 2021
Closes #75, although this leaves open potential issues with history traversal from other documents which we'll track in #78.
@csreis
Copy link

csreis commented Mar 18, 2021

It does look like fragment navigations specifically can be initiated from a cross-origin document and still result in a same-document navigation (rather than loading the document from scratch at the new fragment). In that case, intercepting those might be no worse than status quo.

I am a bit surprised that's allowed in the first place, though-- it seems like it leaks whether the user was still on the same document (e.g., based on watching an iframe's onload?), and could in some scenarios be used for XS-Leaks (e.g., a single-page app that uses fragments to kick off a search query to the server, in which case Sec-Fetch-Site looks same-site).

If there aren't any plans to change that in general, though, then firing the navigate event seems reasonable.

domenic added a commit that referenced this issue Mar 19, 2021
Closes #75, although this leaves open potential issues with history traversal from other documents which we'll track in #78.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
foundational Foundational open questions whose resolution may change the model dramatically
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants