Open oliverdunk opened 3 months ago
@xeenon / @Rob--W, thoughts?
TL;DR: SameSite=Strict
should be included by default, but we should introduce an initiator
property to tabs.create
, tabs.update
and tabs.Tab
to expose the initiator.
By default, browser.tabs.create
mirrors the "user opens a tab", which is a first-party navigation that should include SameSite=Strict cookies.
I would however also like the ability for extensions to opt out of this default behavior, that is to not send SameSite=Strict cookies (but only SameSite=Lax and SameSite=None cookies - see MDN: SameSite). Imagine the use case of an extension that wants to re-open a closed tab (I have created such an extension for myself because Chrome does not offer that feature in incognito mode). The most straightforward way to implement this is to keep track of the list of URLs and then re-open it if the user wants to. The problem with that is that a re-opened tab may then suddenly see a different set of cookies than originally received.
I'm proposing to allow extensions to specify the initiator of a navigation request (in tabs.create
and tabs.update
) and a way to retrieve the initiator of the current tab (tabs.Tab.initiator
). The concept of "initiator" is already present in the extension APIs, specifically webRequest (initiator property, not implemented in Firefox but Firefox has a broader originUrl
) and declarativeNetRequest (initiatorDomains
and excludeInitiatorDomains
rule conditions, and initiator
in the testMatchOutcome
method).
For top-level navigations, the relevant set of cookies are directly derived from the relation between the initiator of the navigation request and the opened destination:
Note: a special case is opaque origins. Opaque origins can be encountered on the web when Content-Security-Policy: sandbox
is used. Such documents have an opaque origin, but its original origin (if it were not sandboxed) is encoded in the so-called "precursor" origin. This precursor is invisible to web pages, and the origin
is serialized as "null"
. This "null"
serialization is also used in webRequest/webNavigation, but the string itself is not sufficiently expressive to capture the precursor. In the initial version I'd be fine with using "null"
as the serialization for opaque origins, because such requests are considered third-party in the context of this issue. For anyone interested in initiator in other contexts (DNR), see https://bugzilla.mozilla.org/show_bug.cgi?id=1798225.
I'll put up a more detailed API proposal when I have some more time (maybe in a month or so).
Firefox (From browser.tabs.create) Seems to require host permissions [1] [1] I wasn't able to find any documentation on this, but that was what seemed to happen in a quick test.
This happens because we internally set the initiator to the extension's base URL, to associate the navigation with the extension. Because initiator is set, the request is no longer considered to be a first-party request unconditionally, and the "usual" third party checks happen. moz-extension:
to something else is considered third-party, unless the extension has host permissions for that destination. I have to carefully examine what we should do.
Note for myself: The extension permission check in BasePrincipal::IsThirdPartyURI
was added in https://bugzilla.mozilla.org/show_bug.cgi?id=1641905
Chrome is aligned with Firefox that SameSite=Strict cookies should be included by default. We are also open to a way to control this through an initiator
property. We have some reservations about adding a tabs.Tab.initiator
since we believe this API should be focused around interacting with tabs, and not be a place for a large amount of data more generally associated with the content inside of them (especially since frames can have an initiator, too). However, we can discuss that more alongside the proposal.
We are open to an initiator
property for Safari/WebKit.
A developer recently filed a Chromium issue with questions about the fact that Chrome sends SameSite=Strict cookies when a site is opened with
browser.tabs.create
. We don't think this is a security issue, but acknowledged it may be useful behavior to clarify across browser vendors.I have done some testing and included my results below. The developer also mentioned opening from an external application as being an interesting test case, so I have included that too.
[1] I wasn't able to find any documentation on this, but that was what seemed to happen in a quick test.
I would lean towards aligning with the behavior from an external application, i.e including them regardless of host permissions.