Prevent top navigations without user activation in some circumstances?
I'm still investigating exactly what is going on here, but between https://github.com/WICG/interventions/issues/16 and https://chromestatus.com/feature/5851021045661696 there is some indication that Chrome shipped a restriction on how much iframes can navigate the top-level frame, beyond the currently-specified restrictions based on sandboxing.
I have found some evidence that:
- This is based on sticky activation, not transient activation
- Something changed in Chrome 102 which is causing people to notice this now; possibly something about resetting sticky activation on redirects
Supposedly Chrome shipped this in Chrome 68, but every few releases someone shows up in https://github.com/WICG/interventions/issues/16 complaining that something new is broken, so it's not clear exactly what Chrome is doing here.
We should:
- Figure out exactly what Chrome has implemented
- See if other browsers are interested in doing so as well
- If so, spec it and write WPTs.
/cc @natechapin @shivanigithub
We're interested in implementing this in Gecko. Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1800190
CC @annevk, it seems Safari also ships this or a variant of this? https://bugs.webkit.org/show_bug.cgi?id=193076
Looks like https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/web_tests/http/tests/security/frameNavigation/ has a number of tests that could maybe be adopted. It appears we implemented this quite a while back to address attacks from ads observed in the wild.
One thing I noticed that isn't mentioned here is that there's a carve-out if the navigation is same-site with the iframe and there's a carve-out for sandboxed iframes. (The relevant code in WebKit seems quite readable by the way, worth looking at https://commits.webkit.org/207754@main and more recent versions of those files when specifying this.)
@domfarolino, you mentioned that you might be available to work on this. I don't mean to commit you if that's changed.
Here is roughly how we implemented it in Firefox:
- Before a target BrowsingContext (BC) is navigated, perform the following checks:
- If the target BC is not top-level, return OK
- If the load has transient user activation, return OK
- If the source BC has sticky user activation, return OK
- If the source BC and the target BC are not part of the same BC tree, return OK
- If the source BC and target BC are same-origin, return OK
- If the source BC is embedded with “allow-top-navigation”, perform the following checks:
- If the source BC has no parent, return OK
- Otherwise, set
sourceBC = sourceBCParentand go to 1.v.
- Otherwise, return ERR
The function performing all the checks can be found here: https://searchfox.org/firefox-main/rev/529fecf1aff6e290cac16b106edfb656db6f5088/docshell/base/BrowsingContext.cpp#2018.
@maltejur worked on the web platform tests which were added here: https://github.com/web-platform-tests/wpt/pull/54792.
Sorry for the late reply.
The chromium logic is primarily starting here.
Going through your steps:
- If the target BC is not top-level, return OK
line 2267
- If the load has transient user activation, return OK
I can't find this explicitly. I think we rely on stick user activation alone, and may have weird corner cases where the transient user activation was from a different browsing context.
- If the source BC has sticky user activation, return OK
line 2271
- If the source BC and the target BC are not part of the same BC tree, return OK
Included in the same check as (1) on line 2267.
- If the source BC and target BC are same-origin, return OK
line 2272
- If the source BC is embedded with “allow-top-navigation”, perform the following checks:>
- If the source BC has no parent, return OK
- Otherwise, set
sourceBC = sourceBCParentand go to 1.v.
chromium's allow-top-navigation logic is irritatingly spread around. But I think we're close enough.
The OK cases not listed here but present in chromium are:
- If popups are allowed (line 2289)
- If target BC and source BC have the same eTLD+1 (lines 2277-2287)