w3c / webextensions

Charter and administrivia for the WebExtensions Community Group (WECG)
Other
600 stars 56 forks source link

Should `browser.tabs.create` send SameSite=Strict cookies? #663

Open oliverdunk opened 3 months ago

oliverdunk commented 3 months ago

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.

Browser From external application (e.g link in a note) From browser.tabs.create
Chrome Included Included
Firefox Included Seems to require host permissions [1]
Safari Included Included

[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.

oliverdunk commented 3 months ago

@xeenon / @Rob--W, thoughts?

Rob--W commented 3 months ago

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

oliverdunk commented 3 months ago

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.

xeenon commented 3 months ago

We are open to an initiator property for Safari/WebKit.