Bug 1922193 - Drop first-party partitioned cookies that don't have CHIPS. r=valentin,cookie-reviewers,edgul,extension-reviewers,sessionstore-reviewers,willdurand,sfoster,webdriver-reviewers,Sasha,whimboo

Differential Revision: https://phabricator.services.mozilla.com/D226125
This commit is contained in:
Tim Huang 2024-11-15 11:05:25 +00:00
parent 94330c8368
commit 1afd1eb494
11 changed files with 78 additions and 22 deletions

View File

@ -74,7 +74,8 @@ var SessionCookiesInternal = {
expiry,
cookie.originAttributes || {},
cookie.sameSite || Ci.nsICookie.SAMESITE_NONE,
cookie.schemeMap || Ci.nsICookie.SCHEME_HTTPS
cookie.schemeMap || Ci.nsICookie.SCHEME_HTTPS,
cookie.isPartitioned
);
} catch (ex) {
console.error(
@ -256,6 +257,10 @@ var CookieStore = {
jscookie.schemeMap = cookie.schemeMap;
}
if (cookie.isPartitioned) {
jscookie.isPartitioned = true;
}
this._entries.set(this._getKeyForCookie(cookie), jscookie);
},

View File

@ -545,6 +545,39 @@ bool CookieCommons::ShouldIncludeCrossSiteCookie(int32_t aSameSiteAttr,
return aSameSiteAttr == nsICookie::SAMESITE_NONE;
}
// static
bool CookieCommons::IsFirstPartyPartitionedCookieWithoutCHIPS(
Cookie* aCookie, const nsACString& aBaseDomain,
const OriginAttributes& aOriginAttributes) {
MOZ_ASSERT(aCookie);
// The cookie is set with partitioned attribute. This is a CHIPS cookies.
if (aCookie->RawIsPartitioned()) {
return false;
}
// The originAttributes is not partitioned. This is not a partitioned cookie.
if (aOriginAttributes.mPartitionKey.IsEmpty()) {
return false;
}
nsAutoString scheme;
nsAutoString baseDomain;
int32_t port;
bool foreignByAncestorContext;
// Bail out early if the partition key is not valid.
if (!OriginAttributes::ParsePartitionKey(aOriginAttributes.mPartitionKey,
scheme, baseDomain, port,
foreignByAncestorContext)) {
return false;
}
// Check whether the base domain of the cookie match the base domain in the
// partitionKey and it is not an ABA context
return aBaseDomain.Equals(NS_ConvertUTF16toUTF8(baseDomain)) &&
!foreignByAncestorContext;
}
bool CookieCommons::IsSafeTopLevelNav(nsIChannel* aChannel) {
if (!aChannel) {
return false;

View File

@ -126,6 +126,10 @@ class CookieCommons final {
bool aInPrivateBrowsing,
bool aUsingStorageAccess);
static bool IsFirstPartyPartitionedCookieWithoutCHIPS(
Cookie* aCookie, const nsACString& aBaseDomain,
const OriginAttributes& aOriginAttributes);
static bool IsSchemeSupported(nsIPrincipal* aPrincipal);
static bool IsSchemeSupported(nsIURI* aURI);
static bool IsSchemeSupported(const nsACString& aScheme);

View File

@ -696,7 +696,7 @@ CookieService::Add(const nsACString& aHost, const nsACString& aPath,
bool aIsSecure, bool aIsHttpOnly, bool aIsSession,
int64_t aExpiry, JS::Handle<JS::Value> aOriginAttributes,
int32_t aSameSite, nsICookie::schemeType aSchemeMap,
JSContext* aCx) {
bool aIsPartitioned, JSContext* aCx) {
OriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
@ -704,8 +704,8 @@ CookieService::Add(const nsACString& aHost, const nsACString& aPath,
}
return AddNative(aHost, aPath, aName, aValue, aIsSecure, aIsHttpOnly,
aIsSession, aExpiry, &attrs, aSameSite, aSchemeMap, false,
nullptr);
aIsSession, aExpiry, &attrs, aSameSite, aSchemeMap,
aIsPartitioned, nullptr);
}
NS_IMETHODIMP_(nsresult)

View File

@ -308,6 +308,15 @@ CookieServiceChild::RecordDocumentCookie(Cookie* aCookie,
CookieCommons::GetBaseDomainFromHost(mTLDService, aCookie->Host(),
baseDomain);
if (CookieCommons::IsFirstPartyPartitionedCookieWithoutCHIPS(
aCookie, baseDomain, aAttrs)) {
COOKIE_LOGSTRING(LogLevel::Error,
("Invalid first-party partitioned cookie without "
"partitioned cookie attribution from the document."));
MOZ_DIAGNOSTIC_ASSERT(false);
return CookieNotificationAction::NoActionNeeded;
}
CookieKey key(baseDomain, aAttrs);
CookiesList* cookiesList = nullptr;
mCookiesMap.Get(key, &cookiesList);

View File

@ -602,6 +602,15 @@ void CookieStorage::AddCookie(CookieParser* aCookieParser,
bool aFromHttp, bool aIsThirdParty,
dom::BrowsingContext* aBrowsingContext,
const nsID* aOperationID) {
if (CookieCommons::IsFirstPartyPartitionedCookieWithoutCHIPS(
aCookie, aBaseDomain, aOriginAttributes)) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader,
"Invalid first-party partitioned cookie without "
"partitioned cookie attribution.");
MOZ_DIAGNOSTIC_ASSERT(false);
return;
}
int64_t currentTime = aCurrentTimeInUsec / PR_USEC_PER_SEC;
CookieListIter exactIter{};

View File

@ -118,6 +118,10 @@ interface nsICookieManager : nsISupports
* the originAttributes of this cookie.
* @param aSameSite
* the SameSite attribute.
* @param aSchemeMap
* the schemes this cookie has been set on. See nsICookie.idl.
* @param aIsPartitioned
* true if the cookie should be stored with the Partitioned attribute.
*/
[implicit_jscontext]
void add(in AUTF8String aHost,
@ -130,7 +134,8 @@ interface nsICookieManager : nsISupports
in int64_t aExpiry,
in jsval aOriginAttributes,
in int32_t aSameSite,
in nsICookie_schemeType aSchemeMap);
in nsICookie_schemeType aSchemeMap,
[optional] in boolean aIsPartitioned);
[notxpcom]
nsresult addNative(in AUTF8String aHost,

View File

@ -298,6 +298,8 @@ class StorageModule extends RootBiDiModule {
schemeType = Ci.nsICookie.SCHEME_HTTP;
}
const isPartitioned = originAttributes.partitionKey?.length > 0;
try {
Services.cookies.add(
domain,
@ -311,7 +313,8 @@ class StorageModule extends RootBiDiModule {
expiry === null ? MAX_COOKIE_EXPIRY : expiry,
originAttributes,
this.#getSameSitePlatformProperty(sameSite),
schemeType
schemeType,
isPartitioned
);
} catch (e) {
throw new lazy.error.UnableToSetCookieError(e);

View File

@ -10,8 +10,3 @@
[test_partition_user_context]
disabled:
if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1877953
[test_partition_context_iframe[cross_origin\]]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1865198
expected:
if not nightly_build: FAIL

View File

@ -1,10 +0,0 @@
[partition.py]
[test_partition_context]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1865198
expected:
if not nightly_build: FAIL
[test_partition_context_iframe[cross_origin\]]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1865198
expected:
if not nightly_build: FAIL

View File

@ -702,6 +702,8 @@ this.cookies = class extends ExtensionAPIPersistent {
schemeType = Ci.nsICookie.SCHEME_FILE;
}
let isPartitioned = originAttributes.partitionKey?.length > 0;
// The permission check may have modified the domain, so use
// the new value instead.
Services.cookies.add(
@ -715,7 +717,8 @@ this.cookies = class extends ExtensionAPIPersistent {
expiry,
originAttributes,
sameSite,
schemeType
schemeType,
isPartitioned
);
return self.cookies.get(details);