All checks were successful
check / check (push) Successful in 22s
- Add etherscanLabels module: scrapes Etherscan address pages for phishing/scam labels (Fake_Phishing*, Exploiter, scam warnings). Integrated as best-effort async check in addressWarnings. - Add phishingDomains module: fetches MetaMask's eth-phishing-detect blocklist (~231K domains) at runtime, caches in memory, refreshes every 24h. Checks hostnames with subdomain matching and whitelist overrides. - Integrate domain phishing checks into all approval flows: connection requests, transaction approvals, and signature requests show a prominent red warning banner when the requesting site is on the MetaMask blocklist. - Add unit tests for both modules (12 tests for etherscanLabels parsing, 15 tests for phishingDomains matching). Closes #114
101 lines
4.9 KiB
JavaScript
101 lines
4.9 KiB
JavaScript
const { parseEtherscanPage } = require("../src/shared/etherscanLabels");
|
|
|
|
describe("etherscanLabels", () => {
|
|
describe("parseEtherscanPage", () => {
|
|
test("detects Fake_Phishing label in title", () => {
|
|
const html = `<html><head><title>Fake_Phishing184810 | Address: 0x00000c07...3ea470000 | Etherscan</title></head><body></body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBe("Fake_Phishing184810");
|
|
expect(result.isPhishing).toBe(true);
|
|
expect(result.warning).toContain("Fake_Phishing184810");
|
|
expect(result.warning).toContain("Phish/Hack");
|
|
});
|
|
|
|
test("detects Fake_Phishing with different number", () => {
|
|
const html = `<html><head><title>Fake_Phishing5169 | Address: 0x3e0defb8...99a7a8a74 | Etherscan</title></head><body></body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBe("Fake_Phishing5169");
|
|
expect(result.isPhishing).toBe(true);
|
|
});
|
|
|
|
test("detects Exploiter label", () => {
|
|
const html = `<html><head><title>Exploiter 42 | Address: 0xabcdef...1234 | Etherscan</title></head><body></body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBe("Exploiter 42");
|
|
expect(result.isPhishing).toBe(true);
|
|
});
|
|
|
|
test("detects scam warning in body text", () => {
|
|
const html =
|
|
`<html><head><title>Address: 0xabcdef...1234 | Etherscan</title></head>` +
|
|
`<body>There are reports that this address was used in a Phishing scam.</body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBeNull();
|
|
expect(result.isPhishing).toBe(true);
|
|
expect(result.warning).toContain("phishing/scam");
|
|
});
|
|
|
|
test("detects scam warning with label in body", () => {
|
|
const html =
|
|
`<html><head><title>SomeScammer | Address: 0xabcdef...1234 | Etherscan</title></head>` +
|
|
`<body>There are reports that this address was used in a scam.</body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBe("SomeScammer");
|
|
expect(result.isPhishing).toBe(true);
|
|
expect(result.warning).toContain("SomeScammer");
|
|
});
|
|
|
|
test("returns clean result for legitimate address", () => {
|
|
const html = `<html><head><title>vitalik.eth | Address: 0xd8dA6BF2...37aA96045 | Etherscan</title></head><body>Overview</body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBe("vitalik.eth");
|
|
expect(result.isPhishing).toBe(false);
|
|
expect(result.warning).toBeNull();
|
|
});
|
|
|
|
test("returns clean result for unlabeled address", () => {
|
|
const html = `<html><head><title>Address: 0x1234567890...abcdef | Etherscan</title></head><body>Overview</body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBeNull();
|
|
expect(result.isPhishing).toBe(false);
|
|
expect(result.warning).toBeNull();
|
|
});
|
|
|
|
test("handles exchange labels correctly (not phishing)", () => {
|
|
const html = `<html><head><title>Coinbase 10 | Address: 0xa9d1e08c...b81d3e43 | Etherscan</title></head><body>Overview</body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBe("Coinbase 10");
|
|
expect(result.isPhishing).toBe(false);
|
|
});
|
|
|
|
test("handles contract names correctly (not phishing)", () => {
|
|
const html = `<html><head><title>Beacon Deposit Contract | Address: 0x00000000...03d7705Fa | Etherscan</title></head><body>Overview</body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBe("Beacon Deposit Contract");
|
|
expect(result.isPhishing).toBe(false);
|
|
});
|
|
|
|
test("handles empty HTML gracefully", () => {
|
|
const result = parseEtherscanPage("");
|
|
expect(result.label).toBeNull();
|
|
expect(result.isPhishing).toBe(false);
|
|
expect(result.warning).toBeNull();
|
|
});
|
|
|
|
test("handles malformed title tag", () => {
|
|
const html = `<html><head><title></title></head><body></body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.label).toBeNull();
|
|
expect(result.isPhishing).toBe(false);
|
|
});
|
|
|
|
test("detects wallet drainer warning", () => {
|
|
const html =
|
|
`<html><head><title>Address: 0xabc...def | Etherscan</title></head>` +
|
|
`<body>This is a known wallet drainer contract.</body></html>`;
|
|
const result = parseEtherscanPage(html);
|
|
expect(result.isPhishing).toBe(true);
|
|
});
|
|
});
|
|
});
|