More precise tracking of implicit origins in tab URLs.
This commit is contained in:
parent
d7e78eda19
commit
96ec2c2a6c
|
@ -103,48 +103,70 @@ var TabGuard = (() => {
|
||||||
|
|
||||||
// we suspect tabs which 1) have not been removed/discarded, 2) are restricted by policy, 3) can run JavaScript
|
// we suspect tabs which 1) have not been removed/discarded, 2) are restricted by policy, 3) can run JavaScript
|
||||||
let suspiciousTabs = [...ties].map(TabCache.get).filter(
|
let suspiciousTabs = [...ties].map(TabCache.get).filter(
|
||||||
tab => tab && !tab.discarded && ns.isEnforced(tab.tabId) &&
|
tab => tab && !tab.discarded && ns.isEnforced(tab.id) &&
|
||||||
(tab.url === "about:blank" || ns.policy.can(tab.url, "script")) // TODO: replace about:blank with actual document.domain / window.opener by injecting a content script
|
(!(tab._isExplicitOrigin = tab._isExplicitOrigin || /^(?:https?|ftps?|file):/.test(tab.url)) || ns.policy.can(tab.url, "script"))
|
||||||
);
|
);
|
||||||
|
|
||||||
let legitDomains = allowedGroups[tabDomain] || new Set([tabDomain]);
|
return suspiciousTabs.length > 0 && (async () => {
|
||||||
|
|
||||||
let otherDomains = new Set(suspiciousTabs.map(tab => getDomain(tab.url)).filter(d => d && !legitDomains.has(d)));
|
let suspiciousDomains = [];
|
||||||
if (otherDomains.size === 0) return; // no cross-site ties, no party
|
await Promise.all(suspiciousTabs.map(async (tab) => {
|
||||||
|
if (!tab._isExplicitOrigin) { // e.g. about:blank
|
||||||
|
// let's try retrieving actual origin
|
||||||
|
tab._externalUrl = tab.url;
|
||||||
|
tab._isExplicitOrigin = true;
|
||||||
|
try {
|
||||||
|
tab.url = await browser.tabs.executeScript(tab.id, {
|
||||||
|
runAt: "document_start",
|
||||||
|
code: "window.origin === 'null' ? window.location.href : window.origin"
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
debug(e);
|
||||||
|
}
|
||||||
|
debug(`Real origin for ${tab._externalUrl} (tab ${tab.id}) is ${tab.url}.`);
|
||||||
|
if (!ns.policy.can(tab.url, "script")) return;
|
||||||
|
}
|
||||||
|
suspiciousDomains.push(getDomain(tab.url));
|
||||||
|
}));
|
||||||
|
|
||||||
if (!requestHeaders.some(h => AUTH_HEADERS_RX.test(h.name))) return; // no auth, no party
|
let legitDomains = allowedGroups[tabDomain] || new Set([tabDomain]);
|
||||||
|
let otherDomains = new Set(suspiciousDomains.filter(d => d && !legitDomains.has(d)));
|
||||||
|
if (otherDomains.size === 0) return; // no cross-site ties, no party
|
||||||
|
|
||||||
// danger zone
|
if (!requestHeaders.some(h => AUTH_HEADERS_RX.test(h.name))) return; // no auth, no party
|
||||||
|
|
||||||
let filterAuth = () => {
|
// danger zone
|
||||||
requestHeaders = requestHeaders.filter(h => !AUTH_HEADERS_RX.test(h.name));
|
|
||||||
debug("[TabGuard] Removing auth headers from %o (%o)", request, requestHeaders);
|
|
||||||
return {requestHeaders};
|
|
||||||
};
|
|
||||||
|
|
||||||
let quietDomains = filteredGroups[tabDomain];
|
let filterAuth = () => {
|
||||||
if (mainFrame) {
|
requestHeaders = requestHeaders.filter(h => !AUTH_HEADERS_RX.test(h.name));
|
||||||
let mustPrompt = (!quietDomains || [...otherDomains].some(d => !quietDomains.has(d)));
|
debug("[TabGuard] Removing auth headers from %o (%o)", request, requestHeaders);
|
||||||
if (mustPrompt) {
|
return {requestHeaders};
|
||||||
return (async () => {
|
};
|
||||||
let options = [
|
|
||||||
{label: _("TabGuard_optAnonymize"), checked: true},
|
let quietDomains = filteredGroups[tabDomain];
|
||||||
{label: _("TabGuard_optAllow")},
|
if (mainFrame) {
|
||||||
];
|
let mustPrompt = (!quietDomains || [...otherDomains].some(d => !quietDomains.has(d)));
|
||||||
let ret = await Prompts.prompt({
|
if (mustPrompt) {
|
||||||
title: _("TabGuard_title"),
|
return (async () => {
|
||||||
message: _("TabGuard_message", [tabDomain, [...otherDomains].join(", ")]),
|
let options = [
|
||||||
options});
|
{label: _("TabGuard_optAnonymize"), checked: true},
|
||||||
if (ret.button !== 0) return {cancel: true};
|
{label: _("TabGuard_optAllow")},
|
||||||
let list = ret.option === 0 ? filteredGroups : allowedGroups;
|
];
|
||||||
otherDomains.add(tabDomain);
|
let ret = await Prompts.prompt({
|
||||||
for (let d of otherDomains) list[d] = otherDomains;
|
title: _("TabGuard_title"),
|
||||||
return list === filteredGroups ? filterAuth() : null;
|
message: _("TabGuard_message", [tabDomain, [...otherDomains].join(", ")]),
|
||||||
})();
|
options});
|
||||||
|
if (ret.button !== 0) return {cancel: true};
|
||||||
|
let list = ret.option === 0 ? filteredGroups : allowedGroups;
|
||||||
|
otherDomains.add(tabDomain);
|
||||||
|
for (let d of otherDomains) list[d] = otherDomains;
|
||||||
|
return list === filteredGroups ? filterAuth() : null;
|
||||||
|
})();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
let mustFilter = mainFrame || quietDomains && [...otherDomains].some(d => quietDomains.has(d))
|
||||||
let mustFilter = mainFrame || quietDomains && [...otherDomains].some(d => quietDomains.has(d))
|
return mustFilter ? filterAuth() : null;
|
||||||
return mustFilter ? filterAuth() : null;
|
})();
|
||||||
},
|
},
|
||||||
postCheck(request) {
|
postCheck(request) {
|
||||||
let {requestId, tabId} = request;
|
let {requestId, tabId} = request;
|
||||||
|
|
Loading…
Reference in New Issue