Skip to content
Snippets Groups Projects
Commit cbb6af14 authored by henry's avatar henry
Browse files

fixup! Bug 40209: Implement Basic Crypto Safety

Bug 42702: Read clipboard in parent actor rather than child.
parent 40f8455d
No related branches found
No related tags found
2 merge requests!1202Bug_43099: 2024 YEC Strings,!1195Crypto Safety: Read clipboard in parent actor rather than child
Pipeline #203519 passed
......@@ -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_zcash_tz_address/dzr62p5/
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,
});
});
......
......@@ -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_zcash_tz_address/dzr62p5/
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)}…`;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment