ma1 pushed to branch tor-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Tor Browser
Commits: cbb6af14 by Henry Wilkes at 2024-09-12T10:51:21+01:00 fixup! Bug 40209: Implement Basic Crypto Safety
Bug 42702: Read clipboard in parent actor rather than child.
- - - - -
2 changed files:
- browser/actors/CryptoSafetyChild.sys.mjs - browser/actors/CryptoSafetyParent.sys.mjs
Changes:
===================================== browser/actors/CryptoSafetyChild.sys.mjs ===================================== @@ -5,12 +5,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-import { Bech32Decode } from "resource://gre/modules/Bech32Decode.sys.mjs"; - import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
+ChromeUtils.defineESModuleGetters(lazy, { + setTimeout: "resource://gre/modules/Timer.sys.mjs", +}); + XPCOMUtils.defineLazyPreferenceGetter( lazy, "isCryptoSafetyEnabled", @@ -18,43 +20,6 @@ XPCOMUtils.defineLazyPreferenceGetter( true // Defaults to true. );
-function looksLikeCryptoAddress(s) { - // P2PKH and P2SH addresses - // https://stackoverflow.com/a/24205650 - const bitcoinAddr = /^[13][a-km-zA-HJ-NP-Z1-9]{25,39}$/; - if (bitcoinAddr.test(s)) { - return true; - } - - // Bech32 addresses - if (Bech32Decode(s) !== null) { - return true; - } - - // regular addresses - const etherAddr = /^0x[a-fA-F0-9]{40}$/; - if (etherAddr.test(s)) { - return true; - } - - // t-addresses - // https://www.reddit.com/r/zec/comments/8mxj6x/simple_regex_to_validate_a_zcas... - const zcashAddr = /^t1[a-zA-Z0-9]{33}$/; - if (zcashAddr.test(s)) { - return true; - } - - // Standard, Integrated, and 256-bit Integrated addresses - // https://monero.stackexchange.com/a/10627 - const moneroAddr = - /^4(?:[0-9AB]|[1-9A-HJ-NP-Za-km-z]{12}(?:[1-9A-HJ-NP-Za-km-z]{30})?)[1-9A-HJ-NP-Za-km-z]{93}$/; - if (moneroAddr.test(s)) { - return true; - } - - return false; -} - export class CryptoSafetyChild extends JSWindowActorChild { handleEvent(event) { if ( @@ -70,13 +35,13 @@ export class CryptoSafetyChild extends JSWindowActorChild { return; }
- this.contentWindow.navigator.clipboard.readText().then(clipText => { - const selection = clipText.replace(/\s+/g, ""); - if (!looksLikeCryptoAddress(selection)) { - return; - } + // We send a message to the parent to inspect the clipboard content. + // NOTE: We wait until next cycle to allow the event to propagate and fill + // the clipboard before being read. + // NOTE: Using navigator.clipboard.readText fails with Wayland. See + // tor-browser#42702. + lazy.setTimeout(() => { this.sendAsyncMessage("CryptoSafety:CopiedText", { - selection, host: this.document.documentURIObject.host, }); });
===================================== browser/actors/CryptoSafetyParent.sys.mjs ===================================== @@ -11,6 +11,7 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, { TorDomainIsolator: "resource://gre/modules/TorDomainIsolator.sys.mjs", + Bech32Decode: "resource://gre/modules/Bech32Decode.sys.mjs", });
ChromeUtils.defineLazyGetter(lazy, "CryptoStrings", function () { @@ -24,6 +25,43 @@ XPCOMUtils.defineLazyPreferenceGetter( true // Defaults to true. );
+function looksLikeCryptoAddress(s) { + // P2PKH and P2SH addresses + // https://stackoverflow.com/a/24205650 + const bitcoinAddr = /^[13][a-km-zA-HJ-NP-Z1-9]{25,39}$/; + if (bitcoinAddr.test(s)) { + return true; + } + + // Bech32 addresses + if (lazy.Bech32Decode(s) !== null) { + return true; + } + + // regular addresses + const etherAddr = /^0x[a-fA-F0-9]{40}$/; + if (etherAddr.test(s)) { + return true; + } + + // t-addresses + // https://www.reddit.com/r/zec/comments/8mxj6x/simple_regex_to_validate_a_zcas... + const zcashAddr = /^t1[a-zA-Z0-9]{33}$/; + if (zcashAddr.test(s)) { + return true; + } + + // Standard, Integrated, and 256-bit Integrated addresses + // https://monero.stackexchange.com/a/10627 + const moneroAddr = + /^4(?:[0-9AB]|[1-9A-HJ-NP-Za-km-z]{12}(?:[1-9A-HJ-NP-Za-km-z]{30})?)[1-9A-HJ-NP-Za-km-z]{93}$/; + if (moneroAddr.test(s)) { + return true; + } + + return false; +} + export class CryptoSafetyParent extends JSWindowActorParent { async receiveMessage(aMessage) { if ( @@ -33,7 +71,24 @@ export class CryptoSafetyParent extends JSWindowActorParent { return; }
- let address = aMessage.data.selection; + // Read the global clipboard. We assume the contents come from the HTTP + // page specified in `aMessage.data.host`. + const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance( + Ci.nsITransferable + ); + trans.init(null); + trans.addDataFlavor("text/plain"); + Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard); + let data = {}; + trans.getTransferData("text/plain", data); + data = data?.value.QueryInterface(Ci.nsISupportsString).data; + + let address = data?.replace(/\s+/g, ""); + + if (!address || !looksLikeCryptoAddress(address)) { + return; + } + if (address.length > 32) { address = `${address.substring(0, 32)}…`; }
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/cbb6af14...
tbb-commits@lists.torproject.org