const { isPhishingDomain, loadConfig, getBlocklistSize, getDeltaSize, hostnameVariants, binarySearch, normalizeDomain, _reset, } = require("../src/shared/phishingDomains"); // The vendored baseline is loaded automatically via require(). // _reset() clears only the delta state, not the vendored baseline. beforeEach(() => { _reset(); }); describe("phishingDomains", () => { describe("hostnameVariants", () => { test("returns exact hostname plus parent domains", () => { const variants = hostnameVariants("sub.evil.com"); expect(variants).toEqual(["sub.evil.com", "evil.com"]); }); test("returns just the hostname for a bare domain", () => { const variants = hostnameVariants("example.com"); expect(variants).toEqual(["example.com"]); }); test("handles deep subdomain chains", () => { const variants = hostnameVariants("a.b.c.d.com"); expect(variants).toEqual([ "a.b.c.d.com", "b.c.d.com", "c.d.com", "d.com", ]); }); test("lowercases hostnames", () => { const variants = hostnameVariants("Evil.COM"); expect(variants).toEqual(["evil.com"]); }); }); describe("binarySearch", () => { const sorted = ["alpha.com", "beta.com", "gamma.com", "zeta.com"]; test("finds existing elements", () => { expect(binarySearch(sorted, "alpha.com")).toBe(true); expect(binarySearch(sorted, "gamma.com")).toBe(true); expect(binarySearch(sorted, "zeta.com")).toBe(true); }); test("returns false for missing elements", () => { expect(binarySearch(sorted, "aaa.com")).toBe(false); expect(binarySearch(sorted, "delta.com")).toBe(false); expect(binarySearch(sorted, "zzz.com")).toBe(false); }); test("handles empty array", () => { expect(binarySearch([], "anything")).toBe(false); }); test("handles single-element array", () => { expect(binarySearch(["only.com"], "only.com")).toBe(true); expect(binarySearch(["only.com"], "other.com")).toBe(false); }); }); describe("normalizeDomain", () => { test("strips *. wildcard prefix", () => { expect(normalizeDomain("*.evil.com")).toBe("evil.com"); expect(normalizeDomain("*.sub.evil.com")).toBe("sub.evil.com"); }); test("lowercases domains", () => { expect(normalizeDomain("Evil.COM")).toBe("evil.com"); expect(normalizeDomain("*.Evil.COM")).toBe("evil.com"); }); test("passes through normal domains unchanged", () => { expect(normalizeDomain("example.com")).toBe("example.com"); }); }); describe("wildcard domain handling", () => { test("wildcard blacklist entries match via loadConfig", () => { loadConfig({ blacklist: ["*.scam-site.com", "normal-scam.com"], whitelist: [], }); // *.scam-site.com is normalized to scam-site.com expect(isPhishingDomain("scam-site.com")).toBe(true); expect(isPhishingDomain("sub.scam-site.com")).toBe(true); expect(isPhishingDomain("normal-scam.com")).toBe(true); }); }); describe("vendored baseline detection", () => { // These tests verify that the vendored phishing-domains.json // is loaded and searchable without any delta loaded. test("getBlocklistSize reflects vendored list (no delta)", () => { // The vendored list has 231k+ domains; delta is empty after reset. expect(getBlocklistSize()).toBeGreaterThan(200000); expect(getDeltaSize()).toBe(0); }); test("returns false for clean domains against vendored list", () => { expect(isPhishingDomain("google.com")).toBe(false); expect(isPhishingDomain("github.com")).toBe(false); }); test("returns false for empty/null hostname", () => { expect(isPhishingDomain("")).toBe(false); expect(isPhishingDomain(null)).toBe(false); }); }); describe("delta (loadConfig) + isPhishingDomain", () => { test("detects domains loaded into delta via loadConfig", () => { loadConfig({ blacklist: ["evil-phishing.com", "scam-swap.xyz"], whitelist: [], }); expect(isPhishingDomain("evil-phishing.com")).toBe(true); expect(isPhishingDomain("scam-swap.xyz")).toBe(true); }); test("detects subdomain of delta-blacklisted domain", () => { loadConfig({ blacklist: ["evil-phishing.com"], whitelist: [], }); expect(isPhishingDomain("app.evil-phishing.com")).toBe(true); expect(isPhishingDomain("sub.app.evil-phishing.com")).toBe(true); }); test("delta whitelist overrides delta blacklist", () => { loadConfig({ blacklist: ["metamask.io"], whitelist: ["metamask.io"], }); expect(isPhishingDomain("metamask.io")).toBe(false); }); test("delta whitelist on parent domain overrides blacklist", () => { loadConfig({ blacklist: ["sub.legit.com"], whitelist: ["legit.com"], }); expect(isPhishingDomain("sub.legit.com")).toBe(false); }); test("case-insensitive matching in delta", () => { loadConfig({ blacklist: ["Evil-Phishing.COM"], whitelist: [], }); expect(isPhishingDomain("evil-phishing.com")).toBe(true); expect(isPhishingDomain("EVIL-PHISHING.COM")).toBe(true); }); test("getDeltaSize reflects loaded delta", () => { loadConfig({ blacklist: ["a.com", "b.com", "c.com"], whitelist: ["d.com"], }); expect(getDeltaSize()).toBe(3); }); test("re-loading config replaces previous delta", () => { loadConfig({ blacklist: ["old-scam.com"], whitelist: [], }); expect(isPhishingDomain("old-scam.com")).toBe(true); loadConfig({ blacklist: ["new-scam.com"], whitelist: [], }); expect(isPhishingDomain("old-scam.com")).toBe(false); expect(isPhishingDomain("new-scam.com")).toBe(true); }); test("handles config with no blacklist/whitelist keys", () => { loadConfig({}); expect(getDeltaSize()).toBe(0); }); }); describe("real-world MetaMask blocklist patterns (via delta)", () => { test("detects known phishing domains loaded as delta", () => { loadConfig({ blacklist: [ "uniswap-trade.web.app", "hopprotocol.pro", "blast-pools.pages.dev", ], whitelist: [], }); expect(isPhishingDomain("uniswap-trade.web.app")).toBe(true); expect(isPhishingDomain("hopprotocol.pro")).toBe(true); expect(isPhishingDomain("blast-pools.pages.dev")).toBe(true); }); test("delta whitelist overrides vendored blacklist entries", () => { // If a domain is in the vendored blacklist but a fresh whitelist // update adds it, the whitelist should win. loadConfig({ blacklist: [], whitelist: ["opensea.io", "metamask.io", "etherscan.io"], }); expect(isPhishingDomain("opensea.io")).toBe(false); expect(isPhishingDomain("metamask.io")).toBe(false); expect(isPhishingDomain("etherscan.io")).toBe(false); }); }); describe("delta + vendored interaction", () => { test("delta blacklist entries are found even with empty vendored match", () => { // This domain is (almost certainly) not in the vendored list const uniqueDomain = "test-unique-domain-not-in-vendored-" + Date.now() + ".example.com"; expect(isPhishingDomain(uniqueDomain)).toBe(false); loadConfig({ blacklist: [uniqueDomain], whitelist: [], }); expect(isPhishingDomain(uniqueDomain)).toBe(true); }); test("getBlocklistSize includes both vendored and delta", () => { const baseSize = getBlocklistSize(); loadConfig({ blacklist: ["new-a.com", "new-b.com"], whitelist: [], }); expect(getBlocklistSize()).toBe(baseSize + 2); }); }); });