From a223031b9851874db04b4c6ccb469586f8bb9556 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 12 Nov 2020 12:14:59 -0500 Subject: [PATCH] Work around Firefox's `data:` favIconUrl leak Related issue: - https://bugzilla.mozilla.org/show_bug.cgi?id=1652925 --- platform/chromium/vapi-background.js | 40 +++++++++++++++++----------- src/js/messaging.js | 27 +++++++++---------- src/js/utils.js | 15 ----------- 3 files changed, 37 insertions(+), 45 deletions(-) diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index e5f06c760..f99af7b9a 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -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; } } diff --git a/src/js/messaging.js b/src/js/messaging.js index 61d3716e6..8c30c1f7a 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -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 diff --git a/src/js/utils.js b/src/js/utils.js index d8decf065..983b75120 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -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; -};