commit
89a4fef1e4
@ -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,58 @@ |
||||
const ObservableStore = require('obs-store') |
||||
const extend = require('xtend') |
||||
const PhishingDetector = require('eth-phishing-detect/src/detector') |
||||
|
||||
// compute phishing lists
|
||||
const PHISHING_DETECTION_CONFIG = require('eth-phishing-detect/src/config.json') |
||||
// every ten minutes
|
||||
const POLLING_INTERVAL = 10 * 60 * 1000 |
||||
|
||||
class BlacklistController { |
||||
|
||||
constructor (opts = {}) { |
||||
const initState = extend({ |
||||
phishing: PHISHING_DETECTION_CONFIG, |
||||
}, opts.initState) |
||||
this.store = new ObservableStore(initState) |
||||
// phishing detector
|
||||
this._phishingDetector = null |
||||
this._setupPhishingDetector(initState.phishing) |
||||
// polling references
|
||||
this._phishingUpdateIntervalRef = null |
||||
} |
||||
|
||||
//
|
||||
// PUBLIC METHODS
|
||||
//
|
||||
|
||||
checkForPhishing (hostname) { |
||||
if (!hostname) return false |
||||
const { result } = this._phishingDetector.check(hostname) |
||||
return result |
||||
} |
||||
|
||||
async updatePhishingList () { |
||||
const response = await fetch('https://api.infura.io/v2/blacklist') |
||||
const phishing = await response.json() |
||||
this.store.updateState({ phishing }) |
||||
this._setupPhishingDetector(phishing) |
||||
return phishing |
||||
} |
||||
|
||||
scheduleUpdates () { |
||||
if (this._phishingUpdateIntervalRef) return |
||||
this._phishingUpdateIntervalRef = setInterval(() => { |
||||
this.updatePhishingList() |
||||
}, POLLING_INTERVAL) |
||||
} |
||||
|
||||
//
|
||||
// PRIVATE METHODS
|
||||
//
|
||||
|
||||
_setupPhishingDetector (config) { |
||||
this._phishingDetector = new PhishingDetector(config) |
||||
} |
||||
} |
||||
|
||||
module.exports = BlacklistController |
@ -1,38 +0,0 @@ |
||||
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 |
||||
|
||||
// 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) |
||||
} |
||||
|
||||
// check if the domain is part of the blacklist.
|
||||
const isBlacklisted = blacklistedDomains && blacklistedDomains.includes(strCurrentTab) |
||||
|
||||
// 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 |
||||
} |
||||
}) |
||||
|
||||
return isBlacklisted || levenshteinMatched |
||||
} |
||||
|
||||
module.exports = isPhish |
@ -1,9 +1,10 @@ |
||||
const promiseToCallback = require('promise-to-callback') |
||||
|
||||
module.exports = function(fn, context) { |
||||
module.exports = function nodeify (fn, context) { |
||||
return function(){ |
||||
const args = [].slice.call(arguments) |
||||
const callback = args.pop() |
||||
if (typeof callback !== 'function') throw new Error('callback is not a function') |
||||
promiseToCallback(fn.apply(context, args))(callback) |
||||
} |
||||
} |
||||
|
@ -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