privacycg / CHIPS

A proposal for a cookie attribute to partition cross-site cookies by top-level site
Other
131 stars 31 forks source link

Add explicit behavior requirement for "Partitioned" attribute on First Party cookies #51

Open LGraber opened 2 years ago

LGraber commented 2 years ago

I could not find anywhere in the proposal that was explicit about this and I know it came up in a Working Group meeting so I am adding this issue to make sure it is tracked. My expectation is that if a service returns a First Party Cookie with the Partitioned attribute, the effect should be to essentially ignore the attribute. The Partitioned attribute should indicate how the cookie should behave in a Third Party context not an indicator that this cookie should only work in a Third Party context. Point being, I would not expect the browser to discard cookies with the Partitioned attribute if they are First Party cookies. For our service, it is very difficult / impossible to tell if the request came from an embedded context and change our behavior at all levels of our code and I would expect that to be similar for others.

If I missed the section in the doc that discusses this, sorry

martinthomson commented 2 years ago

Worth describing this, but I will also point out that the first party cookie could be treated as being automatically partitioned (a double-key with the same value in both components). The only thing that might not work there is the part where partitioned cookies have less storage capacity.

LGraber commented 2 years ago

I suppose it could but I would be confused. If I load that page again later, does that mean the browser now sends all cookies for 'domain A' and 'domain A/domain A'? Doesn't seem to have provided any value?

martinthomson commented 2 years ago

There would only be cookies for a tuple of (top-level site, request site). I only say that because this is how partitioning is implemented in Firefox.

LGraber commented 2 years ago

Interesting, so if I visit a page, "interesting.com" and the server returns 2 cookies, one marked as "Partitioned" (cookieA) and the other not marked as Partitioned (cookieB), what is sent when the page makes Fetch calls? There are no iframes / third-party domains ... just a simple page which happens to mark its cookies as Partitioned just in case it is embedded.

LGraber commented 2 years ago

Ah yes ... Firefox just simply does things automatically so "Partitioned" is only 'added' when it actually is third-party. I think this is a bit different because it is not up to the browser to just choose to make a cookie partitioned. Now the server actually said "Partitioned" and thus could be set on First Party Cookies.

johannhof commented 2 years ago

Is this a dupe of #38?

LGraber commented 2 years ago

Yeah. I noticed that after I opened this. That item doesn't seem to have been resolved. I plan to write up some thoughts in here before the meeting tomorrow

LGraber commented 2 years ago

Recommendation: CHIPS is meant to address third-party cookies and is not meant to have any impact on First Party Cookies. Thus, if a server chooses to always set "Partitioned" for their cookies, when loaded as the top-level domain, the Partitioned attribute will be ignored and no partition-key will be associated with the cookie.

The spec also outlines an expectation on how First Party CHIPS should work in the context of a top-level domain that has an embeded iframe from the same domain, either directly or indirectly via an intermediate third-party frame. The question, though, is whether those cookies will/should have a partition-key associated with them and thus whether they would have access to all of the FirstParty cookies. My contention is that they should not have a partition-key and thus should get access to the FirstParty cookies. If you consider the simple case of a site embedding content from itself simply because this is the design it uses to embed content, then it is pretty basic and doesn't make a lot of sense to block these cookies. It is not clear that the existence of an intermediate frame domain adds any real security issues. If that is true then it is more a discussion of usability and clarity of expected behaviors.

krgovind commented 2 years ago

Thanks for your feedback, @LGraber !

We intended to discuss this at TPAC, but unfortunately ran out of time. See our slide deck (pages 7-8).

We agree with your recommendation on essentially ignoring the Partitioned attribute on cookies set on top-level, as well as when set in same-site-with-top-level contexts. As you suggest, the cookie is therefore “unpartitioned”, and the partition key is null.

This does require us to reconsider the current "Block third-party cookies" behavior in Chrome (and also likely in Firefox) where cookies are always blocked on same-site-with-top-level contexts if there is a cross-site ancestor (for example, A2's cookies are blocked on A2 in A1>B>A2, where ">" represents an "embeds" relationship). We are hoping to pursue that conversation as part of the cross-site cookies standardization discussion in privacycg/meetings/issues/19.

annevk commented 2 years ago

Is that @LGraber's recommendation? One way to read the first paragraph at least is that partitioned cookies shouldn't be able to impact non-partitioned cookies, but if you ignore the Partitioned attribute in certain scenarios they definitely can impact those.

I wonder if this is something the website should be able to make a decision about. (Similar to what SameSite allows for.)

And yeah, can we dupe this into #38?

krgovind commented 2 years ago

Is that @LGraber's recommendation? One way to read the first paragraph at least is that partitioned cookies shouldn't be able to impact non-partitioned cookies, but if you ignore the Partitioned attribute in certain scenarios they definitely can impact those.

Hmm. @LGraber could you clarify? Based on the discussion in PrivacyCG, and the second part of the first paragraph: "...when loaded as the top-level domain, the Partitioned attribute will be ignored and no partition-key will be associated with the cookie.", my understanding is that Lee is asking ease-of-use for developers that need the same resource to be supported in top-level as well as embedded contexts; and would like the user-agent to be forgiving of the Partitioned attribute being specified on top-level documents.

And yeah, can we dupe this into #38?

I hope you don't mind, I dupe'd #38 to this discussion. :)

I did want to re-up this comment from @annevk on that issue:

as currently defined it would allow a partitioned context to set cookies that get replayed in a non-partitioned context, which seems dubious and potentially problematic.

@annevk : To make sure I understand, is the concern here that a cookie set by A2 in A1>B>A2 can be replayed on A1? Or are there other scenarios you're thinking of?

DCtheTall commented 2 years ago

Hey all, thanks for your contributions. I have been thinking over whether or not to ignore the Partitioned attribute when the URL setting the cookie is same-site with the top-level document (i.e. a first-party URL). Below are some thoughts on the choices we can make.

Option 1: Ignore the Partitioned attribute

If we ignore SameSite=Lax/Strict cookies in this context because (1) SameSite protections are already more restrictive than Partitioned and (2) the consequences of ignoring the Partitioned attribute on a SameSite=Lax/Strict cookie are less significant.

Partitioned SameSite=None cookies behave differently than SameSite=None;Partitioned cookies in the following ways:

Finally, on the topic of ABA embeds, if we ignore the Partitioned attribute then A>B>A embeds will get different cookies behavior on their own top-level site than when they are embedded in a cross-site context (e.g. B>A vs. A>B>A).

Option 2: Respect the Partitioned attribute

If we choose to respect the Partitioned attribute even when the top-level document is same-site with the cookie URL, then:

Conclusion

My personal opinion here is that we should respect the Partitioned attribute regardless of whether the top-level document is same-site with the cookie's URL. I think it leads to more consistent behavior between the A>B>A and B>A case. I also think any opportunity to use SameSite=None;Partitioned cookie over an unpartitioned SameSite=None is a privacy positive step.

annevk commented 2 years ago

@krgovind yeah I was thinking about ABA (ABBA? 😊).

LGraber commented 2 years ago

Need clarity then on what happens if the browser receives two cookies with the same name varying in the Partitioned attribute (and Value). If they are going to different cookie jars, they won't overwrite each other but what would be sent back to the server on subsequent requests

DCtheTall commented 2 years ago

Need clarity then on what happens if the browser receives two cookies with the same name varying in the Partitioned attribute (and Value). If they are going to different cookie jars, they won't overwrite each other but what would be sent back to the server on subsequent requests

Right now, Chrome considers two cookies with a different partition key (with a null partition key being different from a non-null one) to be unique, even if they share the same name/domain/path.

FWIW this is not totally unprecedented, since it is possible today for different cookies to share names if one is set with Domain and/or Path.

annevk commented 2 years ago

(This really makes me think we should have a Delete-Cookie header for easier cleanup.)

LGraber commented 2 years ago

Just to make sure I am clear, if a service returns a Partitioned cookie to the browser in a first party context (mydomain), it will be stored in: Jar<mydomain, mydomain> as opposed to unpartitioned cookies which are stored in Jar<mydomain, null>

That means, also, that when a page is loaded from mydomain in the first party context, it will get cookies from both Jar<mydomain,null> AND Jar<mydomain, mydomain>

I think it might actually be helpful to put some type of table in the document that shows cookies in various jars on one axis, pages loaded in different contexts on the other axis, and an indicator as to whether or not the cookie is sent as the cell data.

krgovind commented 2 years ago

Just to make sure I am clear, if a service returns a Partitioned cookie to the browser in a first party context (mydomain), it will be stored in: Jar<mydomain, mydomain> as opposed to unpartitioned cookies which are stored in Jar<mydomain, null>

That means, also, that when a page is loaded from mydomain in the first party context, it will get cookies from both Jar<mydomain,null> AND Jar<mydomain, mydomain>

Yes, that's what the spec currently defines and also what @DCtheTall is advocating for.

I believe the security concern from @annevk is - what happens if mydomain sets the cookie in a nested context - say mydomain embeds 3pdomain embeds mydomain (we refer to this as "ABA" in shorthand). If the inner (mydomain) sets a Partitioned cookie in Jar<mydomain, mydomain>, that cookie gets replayed on the outer A, which could be a security concern. Perhaps we should advise site "A" to specify SameSite=Lax|Strict for sensitive cookies to avoid this scenario? I think the fact that "A" needs to opt-in to SameSite=None might be a sufficient mitigation?

I think it might actually be helpful to put some type of table in the document that shows cookies in various jars on one axis, pages loaded in different contexts on the other axis, and an indicator as to whether or not the cookie is sent as the cell data.

Agreed, writing a table representation is a great idea because there are a lot of scenarios to consider. We'll work on this and respond when we have that.

bvandersloot-mozilla commented 1 year ago

Given Chrome's changed position on the ancestor bit in keying it may be worth revisiting this discussion.

With the ancestor bit being used, I think there is much less reason to respect the Partitioned attribute for first party cookies. Responding to @DCtheTall 's original argument from last October:

Dylan noted the following positives for respecting the partitioned attribute, all of which are gained by adding the ancestor bit.

If we choose to respect the Partitioned attribute even when the top-level document is same-site with the cookie URL, then:

Top level sites can interact with their A>B>A embeds using cookies that will not leak outside the top-level site's partition, even when storage access is granted on other sites. This may change if we decide to https://github.com/privacycg/CHIPS/issues/40.

Indeed, this no longer works if we add the ancestor bit to the partitioning key.

A>B>A embeds will get the same cookie behavior as if they were embedded in a B>A context. They A embed will have access to different cookie jar partitions in each case, but the browser will use the same semantics for each cookie.

Because A>B>A embeds would have the partition key <A,null,crosssite> (or equivalently <A,A,crosssite>) they already have the same behavior as if they were embedded in a B>A context. They don't even get access to their unpartitioned cookies!

A>B>A embeds will not have to rely on unpartitioned SameSite=None cookies and will have more incentive to include the Partitioned attribute in more cookie lines.

Also solved by adding the ancestor bit.

Dylan also pointed out the following downsides to ignoring the Partitioned attribute where unpartitioned cookies are available:

Partitioned SameSite=None cookies behave differently than SameSite=None;Partitioned cookies in the following ways:

Unpartitioned SameSite=None cookies are subject to just the 180 per-domain cookie limit as opposed to the 10 per-partition-per-domain limit (or other https://github.com/privacycg/CHIPS/issues/48).

Surprising devs with more cookie storage isn't necessarily bad.

Unpartitioned SameSite=None cookies are cleared if Clear-Site-Data: "cookies" is sent in other partitions. Partitioned cookies are cleared in the partition the header was received only to avoid cross-site entropy leaks.

Shouldn't a partitioned context's Clear-Site-Data: "cookies" not clear an unpartitioned context? This seems more like an oversight of Clear-Site-Data than a reason to have first-party partitions.

Unpartitioned SameSite=None cookies may be sent on different top-level sites than when they were created if the user grants the cookie's site storage access.

Sure, but what use is a Partitioned SameSite=None cookie with ancestor bit keying anyway? it's key would be <A,A,samesite>, which is only accessible in contexts where SameSite=Strict cookies are available.

bvandersloot-mozilla commented 1 year ago

@DCtheTall: have your thoughts changed since October?

aselya commented 1 year ago

From my conversations with @DCtheTall we both feel that adding the ancestor bit to the partitioned key is the best way forward at this time.

bvandersloot-mozilla commented 1 year ago

That's good to hear! Does that bit in the key change how you feel about Partitioned cookies for same-site cookies? Much of the reason for respecting Partitioned for same-site cookies revolved around that bit not being a part of the key.

DCtheTall commented 11 months ago

Hey @bvandersloot-mozilla, thank you for all of the feedback and apologies for the delay in my response.

I have considered your points and am open to not allowing Partitioned in 1P contexts. My recommendation is that we reject cookies set with Partitioned in same-site (wrt site for cookies) contexts. I think that rejecting the cookie is preferable to ignoring the attribute since it will be confusing to have the same Set-Cookie line result in different-behaving cookies depending on whether the context that request comes from. We are also requesting feedback from developers on whether this change would be disruptive for sites that render content in both 1P and 3P contexts.

Shouldn't a partitioned context's Clear-Site-Data: "cookies" not clear an unpartitioned context? This seems more like an oversight of Clear-Site-Data than a reason to have first-party partitions.

In Chrome, Clear-Site-Data will clear unpartitioned state only if the response is coming from a 1P context or a 3P context with storage access (and therefore unpartitioned cookie access). It is not possible for a 3P context where cookies are blocked to use CSD to clear unpartitioned state elsewhere. Sorry if that was not clear :)

Looking forward to discussing this more on the PrivacyCG call with you tomorrow.

krgovind commented 11 months ago

My recommendation is that we reject cookies set with Partitioned in same-site (wrt site for cookies) contexts.

@DCtheTall Unfortunately, this would run into the concern that @LGraber brought up at the top of this thread:

My expectation is that if a service returns a First Party Cookie with the Partitioned attribute, the effect should be to essentially ignore the attribute. The Partitioned attribute should indicate how the cookie should behave in a Third Party context not an indicator that this cookie should only work in a Third Party context. Point being, I would not expect the browser to discard cookies with the Partitioned attribute if they are First Party cookies. For our service, it is very difficult / impossible to tell if the request came from an embedded context and change our behavior at all levels of our code and I would expect that to be similar for others.

We could potentially solve this by including some request headers to reliably indicate whether the request is coming from a top-level context or embedded context; but based on past experiences with rolling out support for Client Hints, etc., this may be somewhat involved. Essentially, we would need to decide between (a) Always including the request header, which may increase the size of all HTTP requests and cause some servers and/or network middle-boxes to run into issues; or (b) Add an extra roundtrip for the server to request that information to be attached on all subsequent requests.

bvandersloot-mozilla commented 11 months ago

@DCtheTall

I think that rejecting the cookie is preferable to ignoring the attribute since it will be confusing to have the same Set-Cookie line result in different-behaving cookies depending on whether the context that request comes from. We are also requesting feedback from developers on whether this change would be disruptive for sites that render content in both 1P and 3P contexts.

👍 This makes sense. Looking forward to seeing the result of that feedback, and if it corresponds to what we heard in the CG meeting (my impression was that the answer was "yes, that would be disruptive.").

@krgovind:

Essentially, we would need to decide between (a) Always including the request header, which may increase the size of all HTTP requests and cause some servers and/or network middle-boxes to run into issues;

we could gain over half of the size increase back by only sending the header in a non-default case. But this does have some increased complexity for rollout and may not be feasible depending on which case is more popular. I'd imagine partitioned is, and that would be the harder one to elide.

bvandersloot-mozilla commented 11 months ago

I think that @DCtheTall's assessment of our options during the call is correct: (1) retain partitioned semantics in unpartitioned contexts, (2) drop cookies with a partitioned attribute in unpartitioned contexts, or (3) ignore the partitioned attribute on cookies in unpartitioned contexts.

All 3 have downsides: (1) Storage Access API won't have access to cookies and cookie stores get much smaller where developers are including Partitioned as a compat measure, (2) first-party cookies break where developers are including Partitioned as a compat measure, and (3) it will be confusing to have the same Set-Cookie line result in different-behaving cookies depending on whether the context that request comes from (and adding a request header only mitigates this).

I'm much less certain where I fall on this. I had a similar mental model of CHIPS as Lee, to use it as a compat measure where I need a stateful, unauthenticated embed, which led me toward (3). However Dylan raises a very good point about silently differing cookie behavior depending on context. (2) seems to me just as bad of a developer experience, but Dylan knows more about cookies than I do. I do still have my reservations about (1), but maybe eliminating the SameSite=None requirement and clearing up the semantics of the Partitioned attribute to be "use an alternate cookie store that is available in more places" rather than "opt-in to partitioning in order to still get my cookies after 3pcd" would leave this the best answer afterall.

bc-pi commented 11 months ago

We are also requesting feedback from developers on whether this change would be disruptive for sites that render content in both 1P and 3P contexts.

... Looking forward to seeing the result of that feedback, and if it corresponds to what we heard in the CG meeting (my impression was that the answer was "yes, that would be disruptive.").

Echoing what was heard in the CG meeting, from the limited preservative of an application that can be in both/either 1P and 3P contexts and doesn't have a reliable way to differentiate, rejecting a cookie w/ the Partitioned attribute in 1st party context could potentially be very disruptive.

DCtheTall commented 11 months ago

Hey all, thanks for the continued engagement, summarizing what was said on the call:

It seems to me we can rule out option 3, since there is consensus that it is confusing for the same cookie line to result in semantically different cookies depending on the context they are set in.

Since there is no reliable way for apps to identify when they are in a 3P context, there are strong compat reasons to choose option 1 over option 2. I think this could be revisited if/when we ship headers that reveal what type of context a server is responding to, but until then we think we should accept cookies set with Partitioned and set their partition key to be the 1P site.

bvandersloot-mozilla commented 10 months ago

To clear up any ambiguity: I agree with a preference of option 1 over option 2 as well due to the compat concern.