Merge pull request #1849 from MetaMask/blacklist-refactor
Blacklist refactorfeature/default_network_editable
commit
2c37d43888
@ -1,14 +0,0 @@ |
||||
const extension = require('extensionizer') |
||||
|
||||
var port = extension.runtime.connect({name: 'blacklister'}) |
||||
port.postMessage({ 'pageLoaded': window.location.hostname }) |
||||
port.onMessage.addListener(redirectIfBlacklisted) |
||||
|
||||
function redirectIfBlacklisted (response) { |
||||
const { blacklist } = response |
||||
const host = window.location.hostname |
||||
if (blacklist && blacklist === host) { |
||||
window.location.href = 'https://metamask.io/phishing.html' |
||||
} |
||||
} |
||||
|
@ -0,0 +1,50 @@ |
||||
const ObservableStore = require('obs-store') |
||||
const extend = require('xtend') |
||||
const communityBlacklistedDomains = require('etheraddresslookup/blacklists/domains.json') |
||||
const communityWhitelistedDomains = require('etheraddresslookup/whitelists/domains.json') |
||||
const checkForPhishing = require('../lib/is-phish') |
||||
|
||||
// compute phishing lists
|
||||
const PHISHING_BLACKLIST = communityBlacklistedDomains.concat(['metamask.com']) |
||||
const PHISHING_WHITELIST = communityWhitelistedDomains.concat(['metamask.io', 'www.metamask.io']) |
||||
const PHISHING_FUZZYLIST = ['myetherwallet', 'myetheroll', 'ledgerwallet', 'metamask'] |
||||
// every ten minutes
|
||||
const POLLING_INTERVAL = 10 * 60 * 1000 |
||||
|
||||
class BlacklistController { |
||||
|
||||
constructor (opts = {}) { |
||||
const initState = extend({ |
||||
phishing: PHISHING_BLACKLIST, |
||||
}, opts.initState) |
||||
this.store = new ObservableStore(initState) |
||||
// polling references
|
||||
this._phishingUpdateIntervalRef = null |
||||
} |
||||
|
||||
//
|
||||
// PUBLIC METHODS
|
||||
//
|
||||
|
||||
checkForPhishing (hostname) { |
||||
if (!hostname) return false |
||||
const { blacklist } = this.store.getState() |
||||
return checkForPhishing({ hostname, blacklist, whitelist: PHISHING_WHITELIST, fuzzylist: PHISHING_FUZZYLIST }) |
||||
} |
||||
|
||||
async updatePhishingList () { |
||||
const response = await fetch('https://api.infura.io/v1/blacklist') |
||||
const phishing = await response.json() |
||||
this.store.updateState({ phishing }) |
||||
return phishing |
||||
} |
||||
|
||||
scheduleUpdates () { |
||||
if (this._phishingUpdateIntervalRef) return |
||||
this._phishingUpdateIntervalRef = setInterval(() => { |
||||
this.updatePhishingList() |
||||
}, POLLING_INTERVAL) |
||||
} |
||||
} |
||||
|
||||
module.exports = BlacklistController |
@ -1,38 +1,23 @@ |
||||
const levenshtein = require('fast-levenshtein') |
||||
const blacklistedMetaMaskDomains = ['metamask.com'] |
||||
let blacklistedDomains = require('etheraddresslookup/blacklists/domains.json').concat(blacklistedMetaMaskDomains) |
||||
const whitelistedMetaMaskDomains = ['metamask.io', 'www.metamask.io'] |
||||
const whitelistedDomains = require('etheraddresslookup/whitelists/domains.json').concat(whitelistedMetaMaskDomains) |
||||
const LEVENSHTEIN_TOLERANCE = 4 |
||||
const LEVENSHTEIN_CHECKS = ['myetherwallet', 'myetheroll', 'ledgerwallet', 'metamask'] |
||||
|
||||
|
||||
// credit to @sogoiii and @409H for their help!
|
||||
// Return a boolean on whether or not a phish is detected.
|
||||
function isPhish({ hostname, updatedBlacklist = null }) { |
||||
var strCurrentTab = hostname |
||||
function isPhish({ hostname, blacklist, whitelist, fuzzylist }) { |
||||
|
||||
// check if the domain is part of the whitelist.
|
||||
if (whitelistedDomains && whitelistedDomains.includes(strCurrentTab)) { return false } |
||||
|
||||
// Allow updating of blacklist:
|
||||
if (updatedBlacklist) { |
||||
blacklistedDomains = blacklistedDomains.concat(updatedBlacklist) |
||||
} |
||||
if (whitelist && whitelist.includes(hostname)) return false |
||||
|
||||
// check if the domain is part of the blacklist.
|
||||
const isBlacklisted = blacklistedDomains && blacklistedDomains.includes(strCurrentTab) |
||||
if (blacklist && blacklist.includes(hostname)) return true |
||||
|
||||
// check for similar values.
|
||||
let levenshteinMatched = false |
||||
var levenshteinForm = strCurrentTab.replace(/\./g, '') |
||||
LEVENSHTEIN_CHECKS.forEach((element) => { |
||||
if (levenshtein.get(element, levenshteinForm) <= LEVENSHTEIN_TOLERANCE) { |
||||
levenshteinMatched = true |
||||
} |
||||
const levenshteinForm = hostname.replace(/\./g, '') |
||||
const levenshteinMatched = fuzzylist.some((element) => { |
||||
return levenshtein.get(element, levenshteinForm) <= LEVENSHTEIN_TOLERANCE |
||||
}) |
||||
|
||||
return isBlacklisted || levenshteinMatched |
||||
return levenshteinMatched |
||||
} |
||||
|
||||
module.exports = isPhish |
||||
|
@ -0,0 +1,41 @@ |
||||
const assert = require('assert') |
||||
const BlacklistController = require('../../app/scripts/controllers/blacklist') |
||||
|
||||
describe('blacklist controller', function () { |
||||
let blacklistController |
||||
|
||||
before(() => { |
||||
blacklistController = new BlacklistController() |
||||
}) |
||||
|
||||
describe('checkForPhishing', function () { |
||||
it('should not flag whitelisted values', function () { |
||||
const result = blacklistController.checkForPhishing('www.metamask.io') |
||||
assert.equal(result, false) |
||||
}) |
||||
it('should flag explicit values', function () { |
||||
const result = blacklistController.checkForPhishing('metamask.com') |
||||
assert.equal(result, true) |
||||
}) |
||||
it('should flag levenshtein values', function () { |
||||
const result = blacklistController.checkForPhishing('metmask.io') |
||||
assert.equal(result, true) |
||||
}) |
||||
it('should not flag not-even-close values', function () { |
||||
const result = blacklistController.checkForPhishing('example.com') |
||||
assert.equal(result, false) |
||||
}) |
||||
it('should not flag the ropsten faucet domains', function () { |
||||
const result = blacklistController.checkForPhishing('faucet.metamask.io') |
||||
assert.equal(result, false) |
||||
}) |
||||
it('should not flag the mascara domain', function () { |
||||
const result = blacklistController.checkForPhishing('zero.metamask.io') |
||||
assert.equal(result, false) |
||||
}) |
||||
it('should not flag the mascara-faucet domain', function () { |
||||
const result = blacklistController.checkForPhishing('zero-faucet.metamask.io') |
||||
assert.equal(result, false) |
||||
}) |
||||
}) |
||||
}) |
@ -1,24 +0,0 @@ |
||||
const assert = require('assert') |
||||
const isPhish = require('../../app/scripts/lib/is-phish') |
||||
|
||||
describe('blacklister', function () { |
||||
describe('#isPhish', function () { |
||||
it('should not flag whitelisted values', function () { |
||||
var result = isPhish({ hostname: 'www.metamask.io' }) |
||||
assert(!result) |
||||
}) |
||||
it('should flag explicit values', function () { |
||||
var result = isPhish({ hostname: 'metamask.com' }) |
||||
assert(result) |
||||
}) |
||||
it('should flag levenshtein values', function () { |
||||
var result = isPhish({ hostname: 'metmask.com' }) |
||||
assert(result) |
||||
}) |
||||
it('should not flag not-even-close values', function () { |
||||
var result = isPhish({ hostname: 'example.com' }) |
||||
assert(!result) |
||||
}) |
||||
}) |
||||
}) |
||||
|
Loading…
Reference in new issue