Bug 1507769 - User-interaction required before granting storage access for some 3rd party trackers, r=ehsan

We want to introduce a new pref to block trackers that try to workaround our
heuristic. The pref is called:
privacy.restrict3rdpartystorage.userInteractionRequiredForHosts
This commit is contained in:
Andrea Marchesini 2018-11-19 19:16:25 +01:00
Родитель f8679dfb52
Коммит 7fd5fc4b5c
5 изменённых файлов: 90 добавлений и 4 удалений

Просмотреть файл

@ -1375,6 +1375,10 @@ pref("privacy.popups.disable_from_plugins", 3);
// Enable Paritioned LocalStorage for a list of hosts.
pref("privacy.restrict3rdpartystorage.partitionedHosts", "accounts.google.com/o/oauth2/");
// If a host is contained in this pref list, user-interaction is required
// before granting the storage access permission.
pref("privacy.restrict3rdpartystorage.userInteractionRequiredForHosts", "");
// Excessive reporting of blocked popups can be a DOS vector,
// by overloading the main process as popups get blocked and when
// users try to restore all popups, which is the most visible

Просмотреть файл

@ -504,12 +504,15 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(nsIPrincipal* aPrincipa
// We hardcode this block reason since the first-party storage access
// permission is granted for the purpose of blocking trackers.
// Note that if aReason is eOpenerAfterUserInteraction, we don't check the
// Note that if aReason is eOpenerAfterUserInteraction and the
// trackingPrincipal is not in a blacklist, we don't check the
// user-interaction state, because it could be that the current process has
// just sent the request to store the user-interaction permission into the
// parent, without having received the permission itself yet.
const uint32_t blockReason = nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER;
if (aReason != eOpenerAfterUserInteraction &&
if ((aReason != eOpenerAfterUserInteraction ||
nsContentUtils::IsURIInPrefList(trackingURI,
"privacy.restrict3rdpartystorage.userInteractionRequiredForHosts")) &&
!HasUserInteraction(trackingPrincipal)) {
LOG_SPEC(("Tracking principal (%s) hasn't been interacted with before, "
"refusing to add a first-party storage permission to access it",

Просмотреть файл

@ -71,9 +71,71 @@ add_task(async function testLocalStorageEventPropagation() {
info("Removing the tab");
BrowserTestUtils.removeTab(tab);
});
add_task(async function() {
info("Cleaning up.");
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => resolve());
});
});
add_task(async function testBlockedLocalStorageEventPropagation() {
await SpecialPowers.pushPrefEnv({"set": [
["privacy.restrict3rdpartystorage.userInteractionRequiredForHosts", "tracking.example.com,tracking.example.org"],
]});
info("Creating a new tab");
let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
gBrowser.selectedTab = tab;
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
info("Loading tracking scripts");
await ContentTask.spawn(browser, {
page: TEST_3RD_PARTY_DOMAIN + TEST_PATH + "localStorage.html",
}, async obj => {
info("Creating tracker iframe");
let ifr = content.document.createElement("iframe");
ifr.src = obj.page;
await new content.Promise(resolve => {
ifr.onload = function() {
resolve();
};
content.document.body.appendChild(ifr);
});
info("LocalStorage should be blocked.");
await new content.Promise(resolve => {
content.addEventListener("message", e => {
if (e.data.type == "test") {
is(e.data.status, false, "LocalStorage blocked");
} else {
ok(false, "Unknown message");
}
resolve();
}, {once: true});
ifr.contentWindow.postMessage("test", "*");
});
info("Let's open the popup");
await new content.Promise(resolve => {
content.addEventListener("message", e => {
if (e.data.type == "test") {
is(e.data.status, false, "LocalStorage still blocked");
} else {
ok(false, "Unknown message");
}
resolve();
}, {once: true});
ifr.contentWindow.postMessage("open and test", "*");
});
});
info("Removing the tab");
BrowserTestUtils.removeTab(tab);
info("Cleaning up.");
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => resolve());

Просмотреть файл

@ -255,6 +255,7 @@ this.AntiTracking = {
["privacy.trackingprotection.annotate_channels", cookieBehavior != BEHAVIOR_ACCEPT],
[win.ContentBlocking.prefIntroCount, win.ContentBlocking.MAX_INTROS],
["browser.fastblock.enabled", false], // prevent intermittent failures
["privacy.restrict3rdpartystorage.userInteractionRequiredForHosts", "tracking.example.com,tracking.example.org"],
]});
if (extraPrefs && Array.isArray(extraPrefs) && extraPrefs.length) {

Просмотреть файл

@ -24,6 +24,22 @@ if (parent) {
if (e.data == "open") {
window.open("localStorage.html");
return;
}
if (e.data == "open and test") {
let w = window.open("localStorage.html");
w.addEventListener("load", _ => {
let status;
try {
localStorage.foo = "value" + Math.random();
status = true;
} catch (e) {
status = false;
}
parent.postMessage({type: "test", status }, "*");
}, {once: true});
}
};