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

View File

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

View File

@ -683,18 +683,3 @@
window.dispatchEvent(new CustomEvent(name)); 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;
};