Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport changes from latest #129

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.DS_Store
dist/
coverage/

.vscode/
# Logs
logs
*.log
Expand Down
48 changes: 37 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pump from 'pump';
import { toASCII } from 'punycode/';
import { toASCII, toUnicode } from 'punycode/';
import PhishingDetector from 'eth-phishing-detect/src/detector';
import { WindowPostMessageStream } from '@metamask/post-message-stream';
import ObjectMultiplex from 'obj-multiplex';
Expand Down Expand Up @@ -138,6 +138,33 @@ async function isBlockedByMetamask(href: string) {
}
}

/**
* Extract hostname and href from the query string.
*
* @returns The suspect hostname and href from the query string.
* @param href - The href value to check.
*/
function getSuspect(href = ''): {
suspectHostname: string;
suspectHostnameUnicode: string;
suspectHref: string;
suspectHrefUnicode: string;
} {
try {
const url = new URL(href);
const unicodeHostname = toUnicode(url.hostname);
const unicodeHref = `${url.protocol}//${unicodeHostname}${url.pathname}${url.search}${url.hash}`;
return {
suspectHostname: url.hostname,
suspectHostnameUnicode: unicodeHostname,
suspectHref: url.href,
suspectHrefUnicode: unicodeHref,
};
} catch (error) {
throw new Error(`Invalid 'href' query parameter`);
}
}

/**
* Initialize the phishing warning page streams.
*/
Expand All @@ -157,14 +184,13 @@ function start() {
const { hash } = new URL(window.location.href);
const hashContents = hash.slice(1); // drop leading '#' from hash
const hashQueryString = new URLSearchParams(hashContents);
const suspectHostname = hashQueryString.get('hostname');
const suspectHref = hashQueryString.get('href');

if (!suspectHostname) {
throw new Error("Missing 'hostname' query parameter");
} else if (!suspectHref) {
throw new Error("Missing 'href' query parameter");
}
const {
suspectHostname,
suspectHref,
suspectHostnameUnicode,
suspectHrefUnicode,
} = getSuspect(hashQueryString.get('href'));

const suspectLink = document.getElementById('suspect-link');
if (!suspectLink) {
Expand All @@ -178,8 +204,8 @@ function start() {
}

const newIssueParams = `?title=[Legitimate%20Site%20Blocked]%20${encodeURIComponent(
suspectHostname,
)}&body=${encodeURIComponent(suspectHref)}`;
suspectHostnameUnicode,
)}&body=${encodeURIComponent(toUnicode(suspectHrefUnicode))}`;

newIssueLink.addEventListener('click', async () => {
const listName = (await isBlockedByMetamask(suspectHref))
Expand All @@ -194,7 +220,7 @@ function start() {
}

continueLink.addEventListener('click', async () => {
if (isValidSuspectHref(suspectHref) === false) {
if (!isValidSuspectHref(suspectHref)) {
console.log(`Disallowed Protocol, cannot continue.`);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/failed-lookup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ test('directs users to eth-phishing-detect to dispute a block, including issue t
await page.waitForLoadState('networkidle');

await expect(page).toHaveURL(
'https://github.com/MetaMask/eth-phishing-detect/issues/new?title=[Legitimate%20Site%20Blocked]%20test.com&body=https%3A%2F%2Ftest.com',
'https://github.com/MetaMask/eth-phishing-detect/issues/new?title=[Legitimate%20Site%20Blocked]%20test.com&body=https%3A%2F%2Ftest.com%2F',
);
});
28 changes: 3 additions & 25 deletions tests/invalid-inputs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ test.beforeEach(async ({ context }) => {
await setupDefaultMocks(context);
});

test('throws an error about the hostname query parameter being missing', async ({
test('throws an error about the href query parameter being invalid', async ({
context,
page,
}) => {
Expand All @@ -16,29 +16,7 @@ test('throws an error about the hostname query parameter being missing', async (
errorLogs.push(message.text());
}
});

await page.goto('/');

expect(errorLogs.length).toBe(1);
const browserName = context.browser()?.browserType().name();
expect(errorLogs[0]).toMatch(
browserName === 'firefox'
? 'Error' // for some reason the message is missing on Firefox
: `Error: Missing 'hostname' query parameter`,
);
});

test('throws an error about the href query parameter being missing', async ({
context,
page,
}) => {
const errorLogs: string[] = [];
page.on('console', (message) => {
if (message.type() === 'error') {
errorLogs.push(message.text());
}
});
const querystring = new URLSearchParams({ hostname: 'example.com' });
const querystring = new URLSearchParams({});

await page.goto(`/#${querystring}`);

Expand All @@ -47,7 +25,7 @@ test('throws an error about the href query parameter being missing', async ({
expect(errorLogs[0]).toMatch(
browserName === 'firefox'
? 'Error' // for some reason the message is missing on Firefox
: `Error: Missing 'href' query parameter`,
: `Error: Invalid 'href' query parameter`,
);
});

Expand Down
31 changes: 29 additions & 2 deletions tests/metamask-block.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test('directs users to eth-phishing-detect to dispute a block, including issue t
await page.waitForLoadState('networkidle');

await expect(page).toHaveURL(
'https://github.com/MetaMask/eth-phishing-detect/issues/new?title=[Legitimate%20Site%20Blocked]%20test.com&body=https%3A%2F%2Ftest.com',
'https://github.com/MetaMask/eth-phishing-detect/issues/new?title=[Legitimate%20Site%20Blocked]%20test.com&body=https%3A%2F%2Ftest.com%2F',
);
});

Expand All @@ -44,6 +44,33 @@ test('correctly matches unicode domains', async ({ context, page }) => {
await page.waitForLoadState('networkidle');

await expect(page).toHaveURL(
'https://github.com/MetaMask/eth-phishing-detect/issues/new?title=[Legitimate%20Site%20Blocked]%20test.com&body=https%3A%2F%2Fmetamạsk.io',
'https://github.com/MetaMask/eth-phishing-detect/issues/new?title=[Legitimate%20Site%20Blocked]%20metam%E1%BA%A1sk.io&body=https%3A%2F%2Fmetam%E1%BA%A1sk.io%2F',
);
});

test('correctly matches unicode domains with path', async ({
context,
page,
}) => {
await setupDefaultMocks(context, {
phishingConfig: {
...defaultPhishingConfig,
blacklist: ['xn--metamsk-en4c.io'],
},
});
const url = 'https://metamạsk.io/somepath?query=string';
const querystring = new URLSearchParams({
hostname: url,
href: url,
});

await page.goto(`/#${querystring}`);

await page.getByRole('link', { name: 'report a detection problem' }).click();
// Wait for dynamic configuration check
await page.waitForLoadState('networkidle');

await expect(page).toHaveURL(
'https://github.com/MetaMask/eth-phishing-detect/issues/new?title=[Legitimate%20Site%20Blocked]%20metam%E1%BA%A1sk.io&body=https%3A%2F%2Fmetam%E1%BA%A1sk.io%2Fsomepath%3Fquery%3Dstring',
);
});
2 changes: 1 addition & 1 deletion tests/phishfort-block.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ test('directs users to PhishFort to dispute a block, including issue template pa
await page.waitForLoadState('networkidle');

await expect(page).toHaveURL(
'https://github.com/phishfort/phishfort-lists/issues/new?title=[Legitimate%20Site%20Blocked]%20test.com&body=https%3A%2F%2Ftest.com',
'https://github.com/phishfort/phishfort-lists/issues/new?title=[Legitimate%20Site%20Blocked]%20test.com&body=https%3A%2F%2Ftest.com%2F',
);
});