Work around Firefox's `data:` favIconUrl leak

Related issue:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1652925
This commit is contained in:
Raymond Hill 2020-11-12 12:14:59 -05:00
parent 8aa7617372
commit a223031b98
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
3 changed files with 37 additions and 45 deletions

View File

@ -907,10 +907,20 @@ vAPI.messaging = {
port.onMessage.addListener(
(request, port) => this.onPortMessage(request, port)
);
this.ports.set(port.name, {
port,
privileged: port.sender.url.startsWith(this.PRIVILEGED_URL)
});
const portDetails = { port };
const sender = port.sender;
if ( sender ) {
portDetails.frameId = sender.frameId;
const { tab, url } = sender;
if ( tab ) {
portDetails.tabId = tab.id;
}
portDetails.url = url;
portDetails.privileged = url.startsWith(this.PRIVILEGED_URL);
}
this.ports.set(port.name, portDetails);
// https://bugzilla.mozilla.org/show_bug.cgi?id=1652925#c24
port.sender = undefined;
},
setup: function(defaultHandler) {
@ -957,10 +967,8 @@ vAPI.messaging = {
},
onFrameworkMessage: function(request, port, callback) {
const sender = port && port.sender;
if ( !sender ) { return; }
const fromDetails = this.ports.get(port.name) || {};
const tabId = sender.tab && sender.tab.id || undefined;
const portDetails = this.ports.get(port.name) || {};
const tabId = portDetails.tabId;
const msg = request.msg;
switch ( msg.what ) {
case 'connectionAccepted':
@ -1005,7 +1013,7 @@ vAPI.messaging = {
});
break;
case 'localStorage': {
if ( fromDetails.privileged !== true ) { break; }
if ( portDetails.privileged !== true ) { break; }
const args = msg.args || [];
vAPI.localStorage[msg.fn](...args).then(result => {
callback(result);
@ -1016,7 +1024,7 @@ vAPI.messaging = {
if ( tabId === undefined ) { break; }
const details = {
code: undefined,
frameId: sender.frameId,
frameId: portDetails.frameId,
matchAboutBlank: true
};
if ( msg.add ) {
@ -1086,23 +1094,23 @@ vAPI.messaging = {
}
// Auxiliary process to main process: specific handler
const fromDetails = this.ports.get(port.name);
if ( fromDetails === undefined ) { return; }
const portDetails = this.ports.get(port.name);
if ( portDetails === undefined ) { return; }
const listenerDetails = this.listeners.get(request.channel);
let r = this.UNHANDLED;
if (
(listenerDetails !== undefined) &&
(listenerDetails.privileged === false || fromDetails.privileged)
(listenerDetails.privileged === false || portDetails.privileged)
) {
r = listenerDetails.fn(request.msg, port.sender, callback);
r = listenerDetails.fn(request.msg, portDetails, callback);
}
if ( r !== this.UNHANDLED ) { return; }
// Auxiliary process to main process: default handler
if ( fromDetails.privileged ) {
r = this.defaultHandler(request.msg, port.sender, callback);
if ( portDetails.privileged ) {
r = this.defaultHandler(request.msg, portDetails, callback);
if ( r !== this.UNHANDLED ) { return; }
}

View File

@ -42,7 +42,7 @@
const µb = µBlock;
const clickToLoad = function(request, sender) {
const { tabId, frameId } = µb.getMessageSenderDetails(sender);
const { tabId, frameId } = sender;
if ( tabId === undefined || frameId === undefined ) { return false; }
const pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore === null ) { return false; }
@ -545,9 +545,9 @@ vAPI.messaging.listen({
const µb = µBlock;
const retrieveContentScriptParameters = function(senderDetails, request) {
const retrieveContentScriptParameters = function(sender, request) {
if ( µb.readyToFilter !== true ) { return; }
const { url: senderURL, tabId, frameId } = senderDetails;
const { url: senderURL, tabId, frameId } = sender;
if (
tabId === undefined ||
frameId === undefined ||
@ -649,8 +649,7 @@ const onMessage = function(request, sender, callback) {
break;
}
const senderDetails = µb.getMessageSenderDetails(sender);
const pageStore = µb.pageStoreFromTabId(senderDetails.tabId);
const pageStore = µb.pageStoreFromTabId(sender.tabId);
// Sync
let response;
@ -676,29 +675,29 @@ const onMessage = function(request, sender, callback) {
break;
case 'maybeGoodPopup':
µb.maybeGoodPopup.tabId = senderDetails.tabId;
µb.maybeGoodPopup.tabId = sender.tabId;
µb.maybeGoodPopup.url = request.url;
break;
case 'shouldRenderNoscriptTags':
if ( pageStore === null ) { break; }
const fctxt = µb.filteringContext.fromTabId(senderDetails.tabId);
const fctxt = µb.filteringContext.fromTabId(sender.tabId);
if ( pageStore.filterScripting(fctxt, undefined) ) {
vAPI.tabs.executeScript(senderDetails.tabId, {
vAPI.tabs.executeScript(sender.tabId, {
file: '/js/scriptlets/noscript-spoof.js',
frameId: senderDetails.frameId,
frameId: sender.frameId,
runAt: 'document_end',
});
}
break;
case 'retrieveContentScriptParameters':
response = retrieveContentScriptParameters(senderDetails, request);
response = retrieveContentScriptParameters(sender, request);
break;
case 'retrieveGenericCosmeticSelectors':
request.tabId = senderDetails.tabId;
request.frameId = senderDetails.frameId;
request.tabId = sender.tabId;
request.frameId = sender.frameId;
response = {
result: µb.cosmeticFilteringEngine.retrieveGenericSelectors(request),
};
@ -1462,7 +1461,7 @@ vAPI.messaging.listen({
// >>>>> start of local scope
const onMessage = function(request, sender, callback) {
const tabId = sender && sender.tab ? sender.tab.id : 0;
const tabId = sender.tabId || 0;
// Async
switch ( request.what ) {
@ -1614,7 +1613,7 @@ logCSPViolations.policyDirectiveToTypeMap = new Map([
]);
const onMessage = function(request, sender, callback) {
const tabId = sender && sender.tab ? sender.tab.id : 0;
const tabId = sender.tabId || 0;
const pageStore = µb.pageStoreFromTabId(tabId);
// Async

View File

@ -683,18 +683,3 @@
window.dispatchEvent(new CustomEvent(name));
}
};
/******************************************************************************/
µBlock.getMessageSenderDetails = function(sender) {
const r = {};
if ( sender instanceof Object ) {
r.url = sender.url;
r.frameId = sender.frameId;
const tab = sender.tab;
if ( tab instanceof Object ) {
r.tabId = tab.id;
}
}
return r;
};