w3c / webappsec-fetch-metadata

Fetch Metadata
https://w3c.github.io/webappsec-fetch-metadata/
Other
75 stars 28 forks source link

Define `Sec-Fetch-Frame-Ancestors`. #89

Open mikewest opened 6 months ago

mikewest commented 6 months ago

This patch aims to formalize the discussion from w3c/webappsec-fetch-metadata#56, defining a Sec-Fetch-Frame-Ancestors header that supplements Sec-Fetch-Site's exposure of the relationship between a request's initiator and the request's target with additional context about the same-siteness of context within which the request was made. This should support developers' understanding of the viability of various SameSite cookie settings on the one hand, and the ways in which their resources are partitioned on the other.

annevk commented 6 months ago

I wonder if we should allow for two separate pieces of information:

The platform (including our shared understanding of the envisioned platform) makes this distinction in a number of places, though perhaps it's really the latter we want everything to converge upon on given an infinite timescale so perhaps it's reasonable to just expose that. Especially given that we haven't exposed anything for so long.

cc @johannhof

mikewest commented 6 months ago

I agree that the latter (relationship with all ancestors) is where things would ideally converge. It's also what we're using today to make decisions about things like SameSite cookies, and explaining that behavior was one of my goals for this header.

I don't object to exposing the relationship to the top-level document, but it's not clear to me what kinds of decisions that would drive for a server that received the header. I would be also interested in @johannhof's take, as he's a lot closer to the partitioning work than I am these days. @arturjanc and @lweichselbaum might have thoughts from Google's server-side perspective as well.

johannhof commented 6 months ago

I agree that the latter (relationship with all ancestors) is where things would ideally converge. It's also what we're using today to make decisions about things like SameSite cookies, and explaining that behavior was one of my goals for this header.

I think that's also where we want partitioning / third-party cookie blocking to go by default, i.e. roughly the equivalent of SameSite=None being blocked by default, with Storage Access being able to bridge it given permission. Browsers differ in implementations in practice but I do feel like there's good alignment on this goal for security reasons.

The only situation where top-level really makes a difference for web developers then is ABA, right? So, if the developer understood that the resource was cross-site with its ancestors but same-site with its top-level, they might want to utilize storage access got get access to unpartitioned cookies. So I agree this could be useful.

Other related efforts:

CC @dcthetall @shuranhuang @arichiv @cfredric

mikewest commented 6 months ago

We've gotten a lot of feedback around needing a header to understand when a site is in a "partitioned" context, as in third-party cookies / storage are blocked and partitioning is available. It sounds like there's a lot of overlap here so we should probably chat to be able to draw clear lines between this and a potential future proposal :)

I'm confident that things have shifted in the past few years, but I remember talking with @krgovind and @dcthetall about this a while ago. At that point, I suggested keeping this header the way it's defined here (e.g. processing the whole inclusive ancestor chain), and perhaps introducing some other header (e.g. Sec-Fetch-First-Partyness: ?1 or something).

Assuming those are the axes we actually care about, perhaps we could simplify to a four-state enum? Something like Sec-Fetch-Ancestor-Site with potential values of (top-level (or none?), same-site, same-site-with-top-only, cross-site) would still allow clear explanation of SameSite cookie delivery and allow us to push towards that future boundary, but also distinguish today's partitioning cases in helpful ways?

arichiv commented 6 months ago

same-site-with-top-only is the A>B>A embed case? If so that sounds like good coverage, though I could imagine a frame might want to know if it's cross-site with transient storage, that seems less important.

annevk commented 6 months ago

I like the idea of joining the enums. I think we should continue to expose the origin value(s), for websites that want to impose stricter boundaries.

mikewest commented 6 months ago

same-site-with-top-only is the A>B>A embed case? If so that sounds like good coverage, though I could imagine a frame might want to know if it's cross-site with transient storage, that seems less important.

Yes, that's the case it's meant to cover.

I like the idea of joining the enums. I think we should continue to expose the origin value(s), for websites that want to impose stricter boundaries.

So: none, same-origin (e.g. A>A>A), same-site (e.g. A>A`>A), same-site-with-top (e.g. A>B>A), cross-site (e.g. A>B)? Or would you want same-origin-with-top-but-only-same-site-with-ancestors too?

arichiv commented 6 months ago

Maybe we could return a list of applicable categories rather than just a single one? Sites that cared about things like origin could look for same-origin (or maybe even a specific category like same-origin-with-top-but-only-same-site-with-ancestors), but others could just check for same-site in the list.

annevk commented 6 months ago

Yeah, it seems there's six states (a couple combinations don't make sense which is why it's not nine):

  1. same-origin
  2. same-origin-top-only-but-same-site-otherwise
  3. same-origin-top-only-but-cross-site-otherwise
  4. same-site
  5. same-site-top-only-but-cross-site-otherwise
  6. cross-site

Or maybe:

  1. same-origin
  2. same-site-with-same-origin-top
  3. same-site
  4. cross-site-with-same-origin-top
  5. cross-site-with-same-site-top
  6. cross-site
mikewest commented 6 months ago

@annevk: Your latter arrangement seems more conducive to good developer decision-making, but I don't have strong opinions about the naming. I do wonder whether a dictionary would be more appropriate since these really are two semi-independent axes, but being consistent with the rest of fetch metadata probably suggests the single-token approach is the right one.

I think I'd prefer to avoid a list; that feels more difficult for developers to reason about, but I might not be thinking about it the way you are, @arichiv.

arichiv commented 6 months ago

I think @annevk's proposal does cover all existing cases well, my proposal for a list is more about the potential for future expansion. We are designing this based on current partitioning models but if thinking evolved and we had others to add expressing this as a list or a dictionary would be more flexible (servers that didn't care about new tokens in the list or attributes in the dictionary would just ignore them). Otherwise we might be ensuring the need for a new header entirely if partitioning models ever wanted to shift again.

johannhof commented 6 months ago

I think we're going in the right direction here but don't have anything particularly helpful to add to the bikeshed :)

mikewest commented 6 months ago

Thanks all!

I'm unlikely to have a ton of time this week to poke at this PR again to incorporate feedback, but I'm on a plane for too long over the weekend. Should at least be able to solidify the spec then for another round of feedback next week.

arturjanc commented 5 months ago

Thanks @mikewest, this looks broadly reasonable to me. A couple of bikesheds:

  1. WDYT about including an additional value of something like top for top-level navigations and always setting the header? I agree with your point from the PR that this is redundant with Sec-Fetch-Dest: document, but I think that if the header is always present it would make it a bit easier to write server-side logic using the header.
  2. To atone for sending the extra bytes, maybe we could simplify the name to Sec-Fetch-Ancestors? Since we're sending the header also when there's no actual framing (i.e. on subresource requests from the top-level document) it seems like a more general name could fit. Not a hill I'd die on, though :)
johannhof commented 5 months ago

+1 to Sec-Fetch-Ancestors, this is what my brain autocorrects this proposal's name to anyway

mozfreddyb commented 2 days ago

With a bit of a delay and apparently my mind elsewhere, I just came to the same conclusion as this thread 😊 . High level: An indication whether a fetch was made as a popup or not would be great.

johannhof commented 2 days ago

With a bit of a delay and apparently my mind elsewhere, I just came to the same conclusion as this thread 😊 . High level: An indication whether a fetch was made as a popup or not would be great.

Hmm... I might just be missing something but how would you imagine this header to indicate whether a fetch was made from(?) a popup? :)

annevk commented 2 days ago

Yeah, popups is #83. This is about nested documents only.