зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1661151 - The Storage Access API should automatically reject access for cookie policies that don't allow cross-site storage access r=anti-tracking-reviewers,timhuang
Add a test to validate behavior on non-tracking first-party requests Add tests to ensure we don't say we are granting storage access to third parties with cookiePolicies that forbid it Add check near the top of Document::HasStorageAccess to immediately return false when cookiePolicy is REJECT. Add check near the top of Document::RequestStorageAccess to reject when cookiePolicy is REJECT. Add check in Document::RequestStorageAccess to reject when the cookie policy forbids third party cookies Note, BEHAVIOR_LIMIT_FOREIGN is treated like BEHAVIOR_REJECT_FOREIGN, just like in ContentBlocking::ShouldAllowAccessFor Add comparable checks to the priveleged version of RequestStorageAccess This also resolves Bug 1661152 Differential Revision: https://phabricator.services.mozilla.com/D129278
This commit is contained in:
Родитель
e9b6e43371
Коммит
f9d8931809
|
@ -16546,6 +16546,11 @@ already_AddRefed<mozilla::dom::Promise> Document::HasStorageAccess(
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
if (CookieJarSettings()->GetBlockingAllContexts()) {
|
||||
promise->MaybeResolve(false);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
if (IsTopLevelContentDocument()) {
|
||||
promise->MaybeResolve(true);
|
||||
return promise.forget();
|
||||
|
@ -16642,6 +16647,13 @@ already_AddRefed<mozilla::dom::Promise> Document::RequestStorageAccess(
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
// Step 0. If the browser forbids any storage access, reject.
|
||||
if (CookieJarSettings()->GetBlockingAllContexts()) {
|
||||
this->ConsumeTransientUserGestureActivation();
|
||||
promise->MaybeRejectWithUndefined();
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Step 1. If the document already has been granted access, resolve.
|
||||
RefPtr<nsGlobalWindowOuter> outer =
|
||||
nsGlobalWindowOuter::Cast(inner->GetOuterWindow());
|
||||
|
@ -16738,6 +16750,13 @@ already_AddRefed<mozilla::dom::Promise> Document::RequestStorageAccess(
|
|||
// Examples: skip-lists, on-device classification,
|
||||
// user settings, anti-clickjacking heuristics, or prompting the
|
||||
// user for explicit permission. Reject if some rule is not fulfilled.
|
||||
|
||||
if (CookieJarSettings()->GetBlockingAllThirdPartyContexts()) {
|
||||
this->ConsumeTransientUserGestureActivation();
|
||||
promise->MaybeRejectWithUndefined();
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
if (CookieJarSettings()->GetRejectThirdPartyContexts()) {
|
||||
// Only do something special for third-party tracking content.
|
||||
uint32_t antiTrackingRejectedReason = 0;
|
||||
|
@ -16931,6 +16950,13 @@ already_AddRefed<mozilla::dom::Promise> Document::RequestStorageAccessForOrigin(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// If the browser forbids any storage access, reject.
|
||||
if (CookieJarSettings()->GetBlockingAllContexts()) {
|
||||
this->ConsumeTransientUserGestureActivation();
|
||||
promise->MaybeRejectWithUndefined();
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Only enforce third-party checks when there is a reason to enforce them.
|
||||
if (!CookieJarSettings()->GetRejectThirdPartyContexts()) {
|
||||
// If the the thrid party origin is equal to the window's, resolve.
|
||||
|
@ -16945,6 +16971,13 @@ already_AddRefed<mozilla::dom::Promise> Document::RequestStorageAccessForOrigin(
|
|||
}
|
||||
|
||||
// Check any additional rules that the browser has.
|
||||
|
||||
if (CookieJarSettings()->GetBlockingAllThirdPartyContexts()) {
|
||||
this->ConsumeTransientUserGestureActivation();
|
||||
promise->MaybeRejectWithUndefined();
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
if (CookieJarSettings()->GetRejectThirdPartyContexts()) {
|
||||
RefPtr<BrowsingContext> bc = GetBrowsingContext();
|
||||
if (!bc) {
|
||||
|
|
|
@ -218,6 +218,26 @@ CookieJarSettings::GetLimitForeignContexts(bool* aLimitForeignContexts) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CookieJarSettings::GetBlockingAllThirdPartyContexts(
|
||||
bool* aBlockingAllThirdPartyContexts) {
|
||||
// XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
|
||||
// simply rejecting the request to use the storage. In the future, if we
|
||||
// change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
|
||||
// for non-cookie storage types, this may change.
|
||||
*aBlockingAllThirdPartyContexts =
|
||||
mCookieBehavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN ||
|
||||
(!StaticPrefs::network_cookie_rejectForeignWithExceptions_enabled() &&
|
||||
mCookieBehavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CookieJarSettings::GetBlockingAllContexts(bool* aBlockingAllContexts) {
|
||||
*aBlockingAllContexts = mCookieBehavior == nsICookieService::BEHAVIOR_REJECT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CookieJarSettings::GetPartitionForeign(bool* aPartitionForeign) {
|
||||
*aPartitionForeign =
|
||||
|
|
|
@ -36,6 +36,9 @@ interface nsICookieJarSettings : nsISerializable
|
|||
|
||||
[infallible] readonly attribute boolean limitForeignContexts;
|
||||
|
||||
[infallible] readonly attribute boolean blockingAllThirdPartyContexts;
|
||||
|
||||
[infallible] readonly attribute boolean blockingAllContexts;
|
||||
/**
|
||||
* Whether our cookie behavior mandates partitioning third-party content.
|
||||
*/
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
/* import-globals-from antitracking_head.js */
|
||||
|
||||
var settings = [
|
||||
// same-origin no-tracker
|
||||
{
|
||||
name: "Test whether same-origin non-tracker frame has storage access",
|
||||
topPage: TEST_TOP_PAGE,
|
||||
thirdPartyPage: TEST_DOMAIN + TEST_PATH + "3rdParty.html",
|
||||
},
|
||||
// 3rd-party no-tracker
|
||||
{
|
||||
name: "Test whether 3rd-party non-tracker frame has storage access",
|
||||
|
@ -68,6 +74,7 @@ var testCases = [
|
|||
{
|
||||
behavior: BEHAVIOR_ACCEPT, // 0
|
||||
hasStorageAccess: [
|
||||
true /* same-origin non-tracker */,
|
||||
true /* 3rd-party non-tracker */,
|
||||
true /* 3rd-party non-tracker with permission */,
|
||||
true /* 3rd-party tracker */,
|
||||
|
@ -79,6 +86,7 @@ var testCases = [
|
|||
{
|
||||
behavior: BEHAVIOR_REJECT_FOREIGN, // 1
|
||||
hasStorageAccess: [
|
||||
true /* same-origin non-tracker */,
|
||||
false /* 3rd-party non-tracker */,
|
||||
SpecialPowers.Services.prefs.getBoolPref(
|
||||
"network.cookie.rejectForeignWithExceptions.enabled"
|
||||
|
@ -94,17 +102,19 @@ var testCases = [
|
|||
{
|
||||
behavior: BEHAVIOR_REJECT, // 2
|
||||
hasStorageAccess: [
|
||||
false /* same-origin non-tracker */,
|
||||
false /* 3rd-party non-tracker */,
|
||||
false /* 3rd-party non-tracker with permission */,
|
||||
false /* 3rd-party tracker */,
|
||||
false /* 3rd-party tracker with permission */,
|
||||
false /* same-site tracker */,
|
||||
true /* same-origin tracker */,
|
||||
false /* same-origin tracker */,
|
||||
],
|
||||
},
|
||||
{
|
||||
behavior: BEHAVIOR_LIMIT_FOREIGN, // 3
|
||||
hasStorageAccess: [
|
||||
true /* same-origin non-tracker */,
|
||||
false /* 3rd-party non-tracker */,
|
||||
false /* 3rd-party non-tracker with permission */,
|
||||
false /* 3rd-party tracker */,
|
||||
|
@ -116,6 +126,7 @@ var testCases = [
|
|||
{
|
||||
behavior: BEHAVIOR_REJECT_TRACKER, // 4
|
||||
hasStorageAccess: [
|
||||
true /* same-origin non-tracker */,
|
||||
true /* 3rd-party non-tracker */,
|
||||
true /* 3rd-party non-tracker with permission */,
|
||||
false /* 3rd-party tracker */,
|
||||
|
@ -127,6 +138,7 @@ var testCases = [
|
|||
{
|
||||
behavior: BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN, // 5
|
||||
hasStorageAccess: [
|
||||
true /* same-origin non-tracker */,
|
||||
false /* 3rd-party non-tracker */,
|
||||
true /* 3rd-party non-tracker with permission */,
|
||||
false /* 3rd-party tracker */,
|
||||
|
|
|
@ -61,3 +61,95 @@ add_task(async _ => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
AntiTracking._createTask({
|
||||
name:
|
||||
"Test that we never grant access to cookieBehavior=1, when network.cookie.rejectForeignWithExceptions.enabled is set to false",
|
||||
cookieBehavior: BEHAVIOR_REJECT_FOREIGN,
|
||||
allowList: false,
|
||||
callback: async _ => {
|
||||
/* import-globals-from storageAccessAPIHelpers.js */
|
||||
await noStorageAccessInitially();
|
||||
|
||||
await callRequestStorageAccess(null, true);
|
||||
},
|
||||
extraPrefs: [["network.cookie.rejectForeignWithExceptions.enabled", false]],
|
||||
expectedBlockingNotifications: 0,
|
||||
runInPrivateWindow: false,
|
||||
iframeSandbox: null,
|
||||
accessRemoval: null,
|
||||
callbackAfterRemoval: null,
|
||||
thirdPartyPage: TEST_3RD_PARTY_PAGE_HTTP,
|
||||
errorMessageDomains: [
|
||||
"http://tracking.example.org",
|
||||
"http://tracking.example.org",
|
||||
],
|
||||
});
|
||||
|
||||
add_task(async _ => {
|
||||
await new Promise(resolve => {
|
||||
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
|
||||
resolve()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
AntiTracking._createTask({
|
||||
name: "Test that we never grant access to cookieBehavior=2",
|
||||
cookieBehavior: BEHAVIOR_REJECT,
|
||||
allowList: false,
|
||||
callback: async _ => {
|
||||
/* import-globals-from storageAccessAPIHelpers.js */
|
||||
await noStorageAccessInitially();
|
||||
|
||||
await callRequestStorageAccess(null, true);
|
||||
},
|
||||
expectedBlockingNotifications: 0,
|
||||
runInPrivateWindow: false,
|
||||
iframeSandbox: null,
|
||||
accessRemoval: null,
|
||||
callbackAfterRemoval: null,
|
||||
thirdPartyPage: TEST_3RD_PARTY_PAGE_HTTP,
|
||||
errorMessageDomains: [
|
||||
"http://tracking.example.org",
|
||||
"http://tracking.example.org",
|
||||
],
|
||||
});
|
||||
|
||||
add_task(async _ => {
|
||||
await new Promise(resolve => {
|
||||
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
|
||||
resolve()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
AntiTracking._createTask({
|
||||
name: "Test that we never grant access to cookieBehavior=3",
|
||||
cookieBehavior: BEHAVIOR_LIMIT_FOREIGN,
|
||||
allowList: false,
|
||||
callback: async _ => {
|
||||
/* import-globals-from storageAccessAPIHelpers.js */
|
||||
await noStorageAccessInitially();
|
||||
|
||||
await callRequestStorageAccess(null, true);
|
||||
},
|
||||
expectedBlockingNotifications: 0,
|
||||
runInPrivateWindow: false,
|
||||
iframeSandbox: null,
|
||||
accessRemoval: null,
|
||||
callbackAfterRemoval: null,
|
||||
thirdPartyPage: TEST_3RD_PARTY_PAGE_HTTP,
|
||||
errorMessageDomains: [
|
||||
"http://tracking.example.org",
|
||||
"http://tracking.example.org",
|
||||
],
|
||||
});
|
||||
|
||||
add_task(async _ => {
|
||||
await new Promise(resolve => {
|
||||
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
|
||||
resolve()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче