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 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_TOLERANCE = 4 |
||||||
const LEVENSHTEIN_CHECKS = ['myetherwallet', 'myetheroll', 'ledgerwallet', 'metamask'] |
|
||||||
|
|
||||||
|
|
||||||
// credit to @sogoiii and @409H for their help!
|
// credit to @sogoiii and @409H for their help!
|
||||||
// Return a boolean on whether or not a phish is detected.
|
// Return a boolean on whether or not a phish is detected.
|
||||||
function isPhish({ hostname, updatedBlacklist = null }) { |
function isPhish({ hostname, blacklist, whitelist, fuzzylist }) { |
||||||
var strCurrentTab = hostname |
|
||||||
|
|
||||||
// check if the domain is part of the whitelist.
|
// check if the domain is part of the whitelist.
|
||||||
if (whitelistedDomains && whitelistedDomains.includes(strCurrentTab)) { return false } |
if (whitelist && whitelist.includes(hostname)) return false |
||||||
|
|
||||||
// Allow updating of blacklist:
|
|
||||||
if (updatedBlacklist) { |
|
||||||
blacklistedDomains = blacklistedDomains.concat(updatedBlacklist) |
|
||||||
} |
|
||||||
|
|
||||||
// check if the domain is part of the blacklist.
|
// 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.
|
// check for similar values.
|
||||||
let levenshteinMatched = false |
const levenshteinForm = hostname.replace(/\./g, '') |
||||||
var levenshteinForm = strCurrentTab.replace(/\./g, '') |
const levenshteinMatched = fuzzylist.some((element) => { |
||||||
LEVENSHTEIN_CHECKS.forEach((element) => { |
return levenshtein.get(element, levenshteinForm) <= LEVENSHTEIN_TOLERANCE |
||||||
if (levenshtein.get(element, levenshteinForm) <= LEVENSHTEIN_TOLERANCE) { |
|
||||||
levenshteinMatched = true |
|
||||||
} |
|
||||||
}) |
}) |
||||||
|
|
||||||
return isBlacklisted || levenshteinMatched |
return levenshteinMatched |
||||||
} |
} |
||||||
|
|
||||||
module.exports = isPhish |
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