From 2ccc1977bf6c29ab9994c3345b06766a9e4015f8 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 24 Feb 2023 11:39:00 -0330 Subject: [PATCH] Update the PhishingController to v2 and update phishing warning page (#17835) The PhishingController has been updated to v2. This release should dramatically reduce network traffic and double the update speed of the phishing list. This was accomplished by combining both of our phishing configurations into one list (the "stalelist"), then creating a separate list of the changes just the past few days (the "hotlist"). Now users will download a smaller list more frequently (every 30 minutes rather than every hour), whereas the full list is only updated every 4 days. The combined configuration means that we no longer know which list was responsible for each block. The phishing warning page has been updated to dynamically look this information up, to ensure users are still directed to the correct place to dispute a block. This update to the phishing warning page also includes the recent redesign. --- app/scripts/contentscript.js | 7 +- .../metamask-controller.actions.test.js | 16 +- app/scripts/metamask-controller.js | 22 +- app/scripts/metamask-controller.test.js | 16 +- app/scripts/migrations/080.test.js | 108 ++++++++++ app/scripts/migrations/080.ts | 38 ++++ app/scripts/migrations/index.js | 2 + lavamoat/browserify/beta/policy.json | 4 +- lavamoat/browserify/desktop/policy.json | 4 +- lavamoat/browserify/flask/policy.json | 4 +- lavamoat/browserify/main/policy.json | 4 +- package.json | 4 +- shared/constants/phishing.js | 4 - test/e2e/mock-e2e.js | 31 +++ test/e2e/tests/phishing-detection.spec.js | 191 +++++++++++++++--- yarn.lock | 48 ++--- 16 files changed, 395 insertions(+), 108 deletions(-) create mode 100644 app/scripts/migrations/080.test.js create mode 100644 app/scripts/migrations/080.ts delete mode 100644 shared/constants/phishing.js diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 6fbdc741f..73bce1672 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -605,16 +605,13 @@ function notifyInpageOfStreamFailure() { /** * Redirects the current page to a phishing information page - * - * @param data */ -function redirectToPhishingWarning(data = {}) { +function redirectToPhishingWarning() { console.debug('MetaMask: Routing to Phishing Warning page.'); const { hostname, href } = window.location; - const { newIssueUrl } = data; const baseUrl = process.env.PHISHING_WARNING_PAGE_URL; - const querystring = new URLSearchParams({ hostname, href, newIssueUrl }); + const querystring = new URLSearchParams({ hostname, href }); window.location.href = `${baseUrl}#${querystring}`; } diff --git a/app/scripts/metamask-controller.actions.test.js b/app/scripts/metamask-controller.actions.test.js index 64d409ed7..e15a84580 100644 --- a/app/scripts/metamask-controller.actions.test.js +++ b/app/scripts/metamask-controller.actions.test.js @@ -62,19 +62,25 @@ describe('MetaMaskController', function () { beforeEach(function () { nock('https://static.metafi.codefi.network') .persist() - .get('/api/v1/lists/eth_phishing_detect_config.json') + .get('/api/v1/lists/stalelist.json') .reply( 200, JSON.stringify({ version: 2, tolerance: 2, fuzzylist: [], - whitelist: [], - blacklist: ['127.0.0.1'], + allowlist: [], + blocklist: ['127.0.0.1'], + lastUpdated: 0, }), ) - .get('/api/v1/lists/phishfort_hotlist.json') - .reply(200, JSON.stringify(['127.0.0.1'])); + .get('/api/v1/lists/hotlist.json') + .reply( + 200, + JSON.stringify([ + { url: '127.0.0.1', targetList: 'blocklist', timestamp: 0 }, + ]), + ); metamaskController = new MetaMaskController({ showUserConfirmation: noop, encryptor: { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 25ad328cd..9309d1eb8 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -69,7 +69,6 @@ import { TransactionStatus, TransactionType, } from '../../shared/constants/transaction'; -import { PHISHING_NEW_ISSUE_URLS } from '../../shared/constants/phishing'; import { GAS_API_BASE_URL, GAS_DEV_API_BASE_URL, @@ -527,10 +526,11 @@ export default class MetamaskController extends EventEmitter { initState.PhishingController, ); - this.phishingController.maybeUpdatePhishingLists(); + this.phishingController.maybeUpdateState(); if (process.env.IN_TEST) { - this.phishingController.setRefreshInterval(5 * SECOND); + this.phishingController.setHotlistRefreshInterval(5 * SECOND); + this.phishingController.setStalelistRefreshInterval(30 * SECOND); } this.announcementController = new AnnouncementController( @@ -3642,15 +3642,11 @@ export default class MetamaskController extends EventEmitter { if (sender.url) { const { hostname } = new URL(sender.url); - this.phishingController.maybeUpdatePhishingLists(); + this.phishingController.maybeUpdateState(); // Check if new connection is blocked if phishing detection is on const phishingTestResponse = this.phishingController.test(hostname); if (usePhishDetect && phishingTestResponse?.result) { - this.sendPhishingWarning( - connectionStream, - hostname, - phishingTestResponse, - ); + this.sendPhishingWarning(connectionStream, hostname); this.metaMetricsController.trackEvent({ event: EVENT_NAMES.PHISHING_PAGE_DISPLAYED, category: EVENT.CATEGORIES.PHISHING, @@ -3735,15 +3731,11 @@ export default class MetamaskController extends EventEmitter { * @param {*} connectionStream - The duplex stream to the per-page script, * for sending the reload attempt to. * @param {string} hostname - The hostname that triggered the suspicion. - * @param {object} phishingTestResponse - Result of calling `phishingController.test`, - * which is the result of calling eth-phishing-detects detector.check method https://github.com/MetaMask/eth-phishing-detect/blob/master/src/detector.js#L55-L112 */ - sendPhishingWarning(connectionStream, hostname, phishingTestResponse) { - const newIssueUrl = PHISHING_NEW_ISSUE_URLS[phishingTestResponse?.name]; - + sendPhishingWarning(connectionStream, hostname) { const mux = setupMultiplex(connectionStream); const phishingStream = mux.createStream('phishing'); - phishingStream.write({ hostname, newIssueUrl }); + phishingStream.write({ hostname }); } /** diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index 9a4c49684..ab78c3100 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -121,19 +121,25 @@ describe('MetaMaskController', function () { .reply(200, '{"JPY":12415.9}'); nock('https://static.metafi.codefi.network') .persist() - .get('/api/v1/lists/eth_phishing_detect_config.json') + .get('/api/v1/lists/stalelist.json') .reply( 200, JSON.stringify({ version: 2, tolerance: 2, fuzzylist: [], - whitelist: [], - blacklist: ['127.0.0.1'], + allowlist: [], + blocklist: ['127.0.0.1'], + lastUpdated: 0, }), ) - .get('/api/v1/lists/phishfort_hotlist.json') - .reply(200, JSON.stringify(['127.0.0.1'])); + .get('/api/v1/lists/hotlist.json') + .reply( + 200, + JSON.stringify([ + { url: '127.0.0.1', targetList: 'blocklist', timestamp: 0 }, + ]), + ); sandbox.replace(browser, 'runtime', { sendMessage: sandbox.stub().rejects(), diff --git a/app/scripts/migrations/080.test.js b/app/scripts/migrations/080.test.js new file mode 100644 index 000000000..466916318 --- /dev/null +++ b/app/scripts/migrations/080.test.js @@ -0,0 +1,108 @@ +import { migrate, version } from './080'; + +describe('migration #80', () => { + it('updates the version metadata', async () => { + const oldStorage = { + meta: { + version: 79, + }, + data: {}, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.meta).toStrictEqual({ + version, + }); + }); + + it('does not change the state if the phishing controller state does not exist', async () => { + const oldStorage = { + meta: { + version: 79, + }, + data: { test: '123' }, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.data).toStrictEqual(oldStorage.data); + }); + + const nonObjects = [undefined, null, 'test', 1, ['test']]; + + for (const invalidState of nonObjects) { + it(`does not change the state if the phishing controller state is ${invalidState}`, async () => { + const oldStorage = { + meta: { + version: 79, + }, + data: { PhishingController: invalidState }, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.data).toStrictEqual(oldStorage.data); + }); + } + + it('does not change the state if the phishing controller state does not include "phishing" or "lastFetched" properties', async () => { + const oldStorage = { + meta: { + version: 79, + }, + data: { PhishingController: { test: '123' } }, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.data).toStrictEqual(oldStorage.data); + }); + + it('deletes the "phishing" property', async () => { + const oldStorage = { + meta: { + version: 79, + }, + data: { PhishingController: { test: '123', phishing: [] } }, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.data).toStrictEqual({ + PhishingController: { test: '123' }, + }); + }); + + it('deletes the "lastFetched" property', async () => { + const oldStorage = { + meta: { + version: 79, + }, + data: { PhishingController: { test: '123', lastFetched: 100 } }, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.data).toStrictEqual({ + PhishingController: { test: '123' }, + }); + }); + + it('deletes the "phishing" and "lastFetched" properties', async () => { + const oldStorage = { + meta: { + version: 79, + }, + data: { + PhishingController: { test: '123', lastFetched: 100, phishing: [] }, + }, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.data).toStrictEqual({ + PhishingController: { test: '123' }, + }); + }); +}); diff --git a/app/scripts/migrations/080.ts b/app/scripts/migrations/080.ts new file mode 100644 index 000000000..1a2717364 --- /dev/null +++ b/app/scripts/migrations/080.ts @@ -0,0 +1,38 @@ +import { cloneDeep } from 'lodash'; +import { hasProperty, isObject } from '@metamask/utils'; + +export const version = 80; + +/** + * The`@metamask/phishing-controller` state was updated in v2.0.0. + * + * @param originalVersionedData - Versioned MetaMask extension state, exactly what we persist to dist. + * @param originalVersionedData.meta - State metadata. + * @param originalVersionedData.meta.version - The current state version. + * @param originalVersionedData.data - The persisted MetaMask state, keyed by controller. + * @returns Updated versioned MetaMask extension state. + */ +export async function migrate(originalVersionedData: { + meta: { version: number }; + data: Record; +}) { + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + versionedData.data = transformState(versionedData.data); + return versionedData; +} + +function transformState(state: Record) { + if ( + !hasProperty(state, 'PhishingController') || + !isObject(state.PhishingController) + ) { + return state; + } + const { PhishingController } = state; + + delete PhishingController.phishing; + delete PhishingController.lastFetched; + + return state; +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 8f85fb872..496c80c93 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -83,6 +83,7 @@ import m076 from './076'; import m077 from './077'; import m078 from './078'; import m079 from './079'; +import * as m080 from './080'; const migrations = [ m002, @@ -163,6 +164,7 @@ const migrations = [ m077, m078, m079, + m080, ]; export default migrations; diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 93a93aa1d..4da2914dc 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -1266,7 +1266,7 @@ "@metamask/base-controller": true, "@metamask/controller-utils>isomorphic-fetch": true, "@metamask/phishing-controller>@metamask/controller-utils": true, - "@metamask/phishing-controller>eth-phishing-detect": true, + "@metamask/phishing-warning>eth-phishing-detect": true, "punycode": true } }, @@ -1285,7 +1285,7 @@ "ethjs>ethjs-unit": true } }, - "@metamask/phishing-controller>eth-phishing-detect": { + "@metamask/phishing-warning>eth-phishing-detect": { "packages": { "eslint>optionator>fast-levenshtein": true } diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index 5f498221a..79309f375 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -1330,7 +1330,7 @@ "@metamask/base-controller": true, "@metamask/controller-utils>isomorphic-fetch": true, "@metamask/phishing-controller>@metamask/controller-utils": true, - "@metamask/phishing-controller>eth-phishing-detect": true, + "@metamask/phishing-warning>eth-phishing-detect": true, "punycode": true } }, @@ -1349,7 +1349,7 @@ "ethjs>ethjs-unit": true } }, - "@metamask/phishing-controller>eth-phishing-detect": { + "@metamask/phishing-warning>eth-phishing-detect": { "packages": { "eslint>optionator>fast-levenshtein": true } diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 48c20441c..1695b495f 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -1278,7 +1278,7 @@ "@metamask/base-controller": true, "@metamask/controller-utils>isomorphic-fetch": true, "@metamask/phishing-controller>@metamask/controller-utils": true, - "@metamask/phishing-controller>eth-phishing-detect": true, + "@metamask/phishing-warning>eth-phishing-detect": true, "punycode": true } }, @@ -1297,7 +1297,7 @@ "ethjs>ethjs-unit": true } }, - "@metamask/phishing-controller>eth-phishing-detect": { + "@metamask/phishing-warning>eth-phishing-detect": { "packages": { "eslint>optionator>fast-levenshtein": true } diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 93a93aa1d..4da2914dc 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -1266,7 +1266,7 @@ "@metamask/base-controller": true, "@metamask/controller-utils>isomorphic-fetch": true, "@metamask/phishing-controller>@metamask/controller-utils": true, - "@metamask/phishing-controller>eth-phishing-detect": true, + "@metamask/phishing-warning>eth-phishing-detect": true, "punycode": true } }, @@ -1285,7 +1285,7 @@ "ethjs>ethjs-unit": true } }, - "@metamask/phishing-controller>eth-phishing-detect": { + "@metamask/phishing-warning>eth-phishing-detect": { "packages": { "eslint>optionator>fast-levenshtein": true } diff --git a/package.json b/package.json index d537ad53a..2639e49c9 100644 --- a/package.json +++ b/package.json @@ -245,7 +245,7 @@ "@metamask/notification-controller": "^1.0.0", "@metamask/obs-store": "^5.0.0", "@metamask/permission-controller": "^1.0.0", - "@metamask/phishing-controller": "^1.1.2", + "@metamask/phishing-controller": "^2.0.0", "@metamask/post-message-stream": "^6.0.0", "@metamask/providers": "^10.2.1", "@metamask/rate-limit-controller": "^1.0.0", @@ -374,7 +374,7 @@ "@metamask/eslint-config-nodejs": "^9.0.0", "@metamask/eslint-config-typescript": "^9.0.1", "@metamask/forwarder": "^1.1.0", - "@metamask/phishing-warning": "^1.2.1", + "@metamask/phishing-warning": "^2.0.1", "@metamask/test-dapp": "^5.5.0", "@sentry/cli": "^1.58.0", "@storybook/addon-a11y": "^6.5.13", diff --git a/shared/constants/phishing.js b/shared/constants/phishing.js deleted file mode 100644 index 63dea3706..000000000 --- a/shared/constants/phishing.js +++ /dev/null @@ -1,4 +0,0 @@ -export const PHISHING_NEW_ISSUE_URLS = { - MetaMask: 'https://github.com/metamask/eth-phishing-detect/issues/new', - PhishFort: 'https://github.com/phishfort/phishfort-lists/issues/new', -}; diff --git a/test/e2e/mock-e2e.js b/test/e2e/mock-e2e.js index c043bf570..e6da0333d 100644 --- a/test/e2e/mock-e2e.js +++ b/test/e2e/mock-e2e.js @@ -5,6 +5,21 @@ const blacklistedHosts = [ 'sepolia.infura.io', ]; +const HOTLIST_URL = + 'https://static.metafi.codefi.network/api/v1/lists/hotlist.json'; +const STALELIST_URL = + 'https://static.metafi.codefi.network/api/v1/lists/stalelist.json'; + +const emptyHotlist = []; +const emptyStalelist = { + version: 2, + tolerance: 2, + fuzzylist: [], + allowlist: [], + blocklist: [], + lastUpdated: 0, +}; + async function setupMocking(server, testSpecificMock) { await server.forAnyRequest().thenPassThrough({ beforeRequest: (req) => { @@ -341,6 +356,22 @@ async function setupMocking(server, testSpecificMock) { }); testSpecificMock(server); + + // Mocks below this line can be overridden by test-specific mocks + + await server.forGet(STALELIST_URL).thenCallback(() => { + return { + statusCode: 200, + json: emptyStalelist, + }; + }); + + await server.forGet(HOTLIST_URL).thenCallback(() => { + return { + statusCode: 200, + json: emptyHotlist, + }; + }); } module.exports = { setupMocking }; diff --git a/test/e2e/tests/phishing-detection.spec.js b/test/e2e/tests/phishing-detection.spec.js index 897ad66ac..cc30a5ca0 100644 --- a/test/e2e/tests/phishing-detection.spec.js +++ b/test/e2e/tests/phishing-detection.spec.js @@ -2,36 +2,87 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); const FixtureBuilder = require('../fixture-builder'); -const PHISHFORT_CDN_URL = - 'https://static.metafi.codefi.network/api/v1/lists/phishfort_hotlist.json'; +const STALELIST_URL = + 'https://static.metafi.codefi.network/api/v1/lists/stalelist.json'; -describe('Phishing Detection', function () { - async function mockPhishingDetection(mockServer) { - await mockServer - .forGet( - 'https://static.metafi.codefi.network/api/v1/lists/eth_phishing_detect_config.json', - ) - .thenCallback(() => { - return { - statusCode: 200, - json: { - version: 2, - tolerance: 2, - fuzzylist: [], - whitelist: [], - blacklist: ['127.0.0.1'], - }, - }; - }); - } - async function mockPhishfortPhishingDetection(mockServer) { - await mockServer.forGet(PHISHFORT_CDN_URL).thenCallback(() => { +const emptyHtmlPage = ` + + + + title + + + Empty page + +`; + +/** + * Setup fetch mocks for the phishing detection feature. + * + * The mock configuration will show that "127.0.0.1" is blocked. The dynamic lookup on the warning + * page can be customized, so that we can test both the MetaMask and PhishFort block cases. + * + * @param {import('mockttp').Mockttp} mockServer - The mock server. + * @param {object} metamaskPhishingConfigResponse - The response for the dynamic phishing + * configuration lookup performed by the warning page. + */ +async function setupPhishingDetectionMocks( + mockServer, + metamaskPhishingConfigResponse, +) { + await mockServer.forGet(STALELIST_URL).thenCallback(() => { + return { + statusCode: 200, + json: { + version: 2, + tolerance: 2, + fuzzylist: [], + allowlist: [], + blocklist: ['127.0.0.1'], + lastUpdated: 0, + }, + }; + }); + + await mockServer + .forGet('https://github.com/MetaMask/eth-phishing-detect/issues/new') + .thenCallback(() => { return { statusCode: 200, - json: ['127.0.0.1'], + body: emptyHtmlPage, }; }); + await mockServer + .forGet('https://github.com/phishfort/phishfort-lists/issues/new') + .thenCallback(() => { + return { + statusCode: 200, + body: emptyHtmlPage, + }; + }); + + await mockServer + .forGet( + 'https://raw.githubusercontent.com/MetaMask/eth-phishing-detect/master/src/config.json', + ) + .thenCallback(() => metamaskPhishingConfigResponse); +} + +describe('Phishing Detection', function () { + function mockPhishingDetection(mockServer) { + setupPhishingDetectionMocks(mockServer, { + statusCode: 200, + json: { + version: 2, + tolerance: 2, + fuzzylist: [], + whitelist: [], + blacklist: ['127.0.0.1'], + lastUpdated: 0, + }, + }); } + const ganacheOptions = { accounts: [ { @@ -41,6 +92,7 @@ describe('Phishing Detection', function () { }, ], }; + it('should display the MetaMask Phishing Detection page and take the user to the blocked page if they continue', async function () { await withFixtures( { @@ -57,7 +109,7 @@ describe('Phishing Detection', function () { await driver.press('#password', driver.Key.ENTER); await driver.openNewPage('http://127.0.0.1:8080'); await driver.clickElement({ - text: 'continuing at your own risk', + text: 'continue to the site.', }); const header = await driver.findElement('h1'); assert.equal(await header.getText(), 'E2E Test Dapp'); @@ -93,7 +145,7 @@ describe('Phishing Detection', function () { }); await driver.switchToWindowWithTitle('MetaMask Phishing Detection'); await driver.clickElement({ - text: 'continuing at your own risk', + text: 'continue to the site.', }); const header = await driver.findElement('h1'); assert.equal(await header.getText(), 'E2E Test Dapp'); @@ -131,7 +183,7 @@ describe('Phishing Detection', function () { }); await driver.switchToWindowWithTitle('MetaMask Phishing Detection'); await driver.clickElement({ - text: 'continuing at your own risk', + text: 'continue to the site.', }); // Ensure we're not on the wallet home page @@ -140,13 +192,15 @@ describe('Phishing Detection', function () { ); }); - it('should display the MetaMask Phishing Detection page with the correct new issue link if the issue was detected from the phishfort list', async function () { + it('should navigate the user to eth-phishing-detect to dispute a block if the phishing warning page fails to identify the source', async function () { await withFixtures( { fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, - testSpecificMock: mockPhishfortPhishingDetection, + testSpecificMock: (mockServer) => { + setupPhishingDetectionMocks(mockServer, { statusCode: 500 }); + }, dapp: true, failOnConsoleError: false, }, @@ -155,10 +209,83 @@ describe('Phishing Detection', function () { await driver.fill('#password', 'correct horse battery staple'); await driver.press('#password', driver.Key.ENTER); await driver.openNewPage('http://127.0.0.1:8080'); - const newIssueLink = await driver.findElements( - "a[href='https://github.com/phishfort/phishfort-lists/issues/new?title=[Legitimate%20Site%20Blocked]%20127.0.0.1&body=http%3A%2F%2F127.0.0.1%3A8080%2F']", + + await driver.clickElement({ text: 'report a detection problem.' }); + + // wait for page to load before checking URL. + await driver.findElement({ text: 'Empty page' }); + assert.equal( + await driver.getCurrentUrl(), + `https://github.com/MetaMask/eth-phishing-detect/issues/new?title=[Legitimate%20Site%20Blocked]%20127.0.0.1&body=http%3A%2F%2F127.0.0.1%3A8080%2F`, + ); + }, + ); + }); + + it('should navigate the user to eth-phishing-detect to dispute a block from MetaMask', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions, + title: this.test.title, + testSpecificMock: mockPhishingDetection, + dapp: true, + failOnConsoleError: false, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + await driver.openNewPage('http://127.0.0.1:8080'); + + await driver.clickElement({ text: 'report a detection problem.' }); + + // wait for page to load before checking URL. + await driver.findElement({ text: 'Empty page' }); + assert.equal( + await driver.getCurrentUrl(), + `https://github.com/MetaMask/eth-phishing-detect/issues/new?title=[Legitimate%20Site%20Blocked]%20127.0.0.1&body=http%3A%2F%2F127.0.0.1%3A8080%2F`, + ); + }, + ); + }); + + it('should navigate the user to PhishFort to dispute a block from MetaMask', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions, + title: this.test.title, + testSpecificMock: (mockServer) => { + setupPhishingDetectionMocks(mockServer, { + statusCode: 200, + json: { + version: 2, + tolerance: 2, + fuzzylist: [], + whitelist: [], + blacklist: [], + lastUpdated: 0, + }, + }); + }, + dapp: true, + failOnConsoleError: false, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + await driver.openNewPage('http://127.0.0.1:8080'); + + await driver.clickElement({ text: 'report a detection problem.' }); + + // wait for page to load before checking URL. + await driver.findElement({ text: 'Empty page' }); + assert.equal( + await driver.getCurrentUrl(), + `https://github.com/phishfort/phishfort-lists/issues/new?title=[Legitimate%20Site%20Blocked]%20127.0.0.1&body=http%3A%2F%2F127.0.0.1%3A8080%2F`, ); - assert.equal(newIssueLink.length, 1); }, ); }); diff --git a/yarn.lock b/yarn.lock index 53692b511..cc9027552 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4033,9 +4033,9 @@ __metadata: languageName: node linkType: hard -"@metamask/phishing-controller@npm:^1.1.2": - version: 1.1.2 - resolution: "@metamask/phishing-controller@npm:1.1.2" +"@metamask/phishing-controller@npm:^2.0.0": + version: 2.0.0 + resolution: "@metamask/phishing-controller@npm:2.0.0" dependencies: "@metamask/base-controller": ^1.1.2 "@metamask/controller-utils": ^2.0.0 @@ -4043,31 +4043,24 @@ __metadata: eth-phishing-detect: ^1.2.0 isomorphic-fetch: ^3.0.0 punycode: ^2.1.1 - checksum: a85427c5c0adab2651c9fb0207cae9501597b820d0807c35177615533bba2626a4c2458b4863f0bef987cc5dfbd523d70a60d3c48bd332ebc8bd6b5a8f640c4e + checksum: 8ad20a7cdac8fc5f450bb157d19b0b780d82490571f4d33e1afde871ace078cf4f885e2e5be4abc6e1e551986d5f44a3200b076d5545764f5492dfaf005419e4 languageName: node linkType: hard -"@metamask/phishing-warning@npm:^1.2.1": - version: 1.2.1 - resolution: "@metamask/phishing-warning@npm:1.2.1" +"@metamask/phishing-warning@npm:^2.0.1": + version: 2.0.1 + resolution: "@metamask/phishing-warning@npm:2.0.1" dependencies: "@metamask/design-tokens": ^1.6.0 - "@metamask/post-message-stream": ^5.1.0 + "@metamask/post-message-stream": ^6.0.0 + "@types/punycode": ^2.1.0 + eth-phishing-detect: ^1.2.0 globalthis: 1.0.1 obj-multiplex: ^1.0.0 pump: ^3.0.0 - ses: 0.12.4 - checksum: 5cdf2f5fb12dbf774c6d54670051ecd02c489f3f0a5ae68a3facbb2135347be3fe308e260fb44e1a34310fe20cb8e26c3b7b0a3addfdd70ca26ff6ba22f22d92 - languageName: node - linkType: hard - -"@metamask/post-message-stream@npm:^5.1.0": - version: 5.1.0 - resolution: "@metamask/post-message-stream@npm:5.1.0" - dependencies: - "@metamask/utils": ^2.0.0 - readable-stream: 2.3.3 - checksum: d6c66d82b94970a0689f2d78e4011b891a48edb0f397b54d657c10506cfc066298f3198203a6e8ec090ba87705d62c0db5ba409fede209e1612c8028160059da + punycode: ^2.1.1 + ses: ^0.18.1 + checksum: caa3e596c3a67188e457307b43724c89121d60734353922d369932093f8618f96465ba7613b194dc2c57754399783dcdf1777c900afeff21bd5137f02688b686 languageName: node linkType: hard @@ -4304,15 +4297,6 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^2.0.0": - version: 2.1.0 - resolution: "@metamask/utils@npm:2.1.0" - dependencies: - fast-deep-equal: ^3.1.3 - checksum: 50970fe28cbf98fbc34fb4f69d9bc90f5db94929c69ab532f57b48f42163ea77fb080ab31854efd984361c3e29e67831a78d94d1211ac3bcc6b9557769c73127 - languageName: node - linkType: hard - "@metamask/utils@npm:^3.0.1, @metamask/utils@npm:^3.0.3, @metamask/utils@npm:^3.3.0, @metamask/utils@npm:^3.3.1, @metamask/utils@npm:^3.4.0, @metamask/utils@npm:^3.4.1, @metamask/utils@npm:^3.6.0": version: 3.6.0 resolution: "@metamask/utils@npm:3.6.0" @@ -24063,8 +24047,8 @@ __metadata: "@metamask/notification-controller": ^1.0.0 "@metamask/obs-store": ^5.0.0 "@metamask/permission-controller": ^1.0.0 - "@metamask/phishing-controller": ^1.1.2 - "@metamask/phishing-warning": ^1.2.1 + "@metamask/phishing-controller": ^2.0.0 + "@metamask/phishing-warning": ^2.0.1 "@metamask/post-message-stream": ^6.0.0 "@metamask/providers": ^10.2.1 "@metamask/rate-limit-controller": ^1.0.0 @@ -30640,7 +30624,7 @@ __metadata: languageName: node linkType: hard -"ses@npm:0.12.4, ses@npm:^0.12.4": +"ses@npm:^0.12.4": version: 0.12.4 resolution: "ses@npm:0.12.4" dependencies: