parent
094e4cf555
commit
77d3bc252d
@ -1,136 +0,0 @@ |
|||||||
const ObservableStore = require('obs-store') |
|
||||||
const extend = require('xtend') |
|
||||||
const PhishingDetector = require('eth-phishing-detect/src/detector') |
|
||||||
const log = require('loglevel') |
|
||||||
|
|
||||||
// compute phishing lists
|
|
||||||
const PHISHING_DETECTION_CONFIG = require('eth-phishing-detect/src/config.json') |
|
||||||
// every four minutes
|
|
||||||
const POLLING_INTERVAL = 4 * 60 * 1000 |
|
||||||
|
|
||||||
class BlacklistController { |
|
||||||
|
|
||||||
/** |
|
||||||
* Responsible for polling for and storing an up to date 'eth-phishing-detect' config.json file, while |
|
||||||
* exposing a method that can check whether a given url is a phishing attempt. The 'eth-phishing-detect' |
|
||||||
* config.json file contains a fuzzylist, whitelist and blacklist. |
|
||||||
* |
|
||||||
* |
|
||||||
* @typedef {Object} BlacklistController |
|
||||||
* @param {object} opts Overrides the defaults for the initial state of this.store |
|
||||||
* @property {object} store The the store of the current phishing config |
|
||||||
* @property {object} store.phishing Contains fuzzylist, whitelist and blacklist arrays. @see |
|
||||||
* {@link https://github.com/MetaMask/eth-phishing-detect/blob/master/src/config.json}
|
|
||||||
* @property {object} _phishingDetector The PhishingDetector instantiated by passing store.phishing to |
|
||||||
* PhishingDetector. |
|
||||||
* @property {object} _phishingUpdateIntervalRef Id of the interval created to periodically update the blacklist |
|
||||||
* |
|
||||||
*/ |
|
||||||
constructor (opts = {}) { |
|
||||||
const initState = extend({ |
|
||||||
phishing: PHISHING_DETECTION_CONFIG, |
|
||||||
whitelist: [], |
|
||||||
}, opts.initState) |
|
||||||
this.store = new ObservableStore(initState) |
|
||||||
// phishing detector
|
|
||||||
this._phishingDetector = null |
|
||||||
this._setupPhishingDetector(initState.phishing) |
|
||||||
// polling references
|
|
||||||
this._phishingUpdateIntervalRef = null |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Adds the given hostname to the runtime whitelist |
|
||||||
* @param {string} hostname the hostname to whitelist |
|
||||||
*/ |
|
||||||
whitelistDomain (hostname) { |
|
||||||
if (!hostname) { |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
const { whitelist } = this.store.getState() |
|
||||||
this.store.updateState({ |
|
||||||
whitelist: [...new Set([hostname, ...whitelist])], |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Given a url, returns the result of checking if that url is in the store.phishing blacklist |
|
||||||
* |
|
||||||
* @param {string} hostname The hostname portion of a url; the one that will be checked against the white and |
|
||||||
* blacklists of store.phishing |
|
||||||
* @returns {boolean} Whether or not the passed hostname is on our phishing blacklist |
|
||||||
* |
|
||||||
*/ |
|
||||||
checkForPhishing (hostname) { |
|
||||||
if (!hostname) return false |
|
||||||
|
|
||||||
const { whitelist } = this.store.getState() |
|
||||||
if (whitelist.some((e) => e === hostname)) { |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
const { result } = this._phishingDetector.check(hostname) |
|
||||||
return result |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Queries `https://api.infura.io/v2/blacklist` for an updated blacklist config. This is passed to this._phishingDetector |
|
||||||
* to update our phishing detector instance, and is updated in the store. The new phishing config is returned |
|
||||||
* |
|
||||||
* |
|
||||||
* @returns {Promise<object>} Promises the updated blacklist config for the phishingDetector |
|
||||||
* |
|
||||||
*/ |
|
||||||
async updatePhishingList () { |
|
||||||
// make request
|
|
||||||
let response |
|
||||||
try { |
|
||||||
response = await fetch('https://api.infura.io/v2/blacklist') |
|
||||||
} catch (err) { |
|
||||||
log.error(new Error(`BlacklistController - failed to fetch blacklist:\n${err.stack}`)) |
|
||||||
return |
|
||||||
} |
|
||||||
// parse response
|
|
||||||
let rawResponse |
|
||||||
let phishing |
|
||||||
try { |
|
||||||
const rawResponse = await response.text() |
|
||||||
phishing = JSON.parse(rawResponse) |
|
||||||
} catch (err) { |
|
||||||
log.error(new Error(`BlacklistController - failed to parse blacklist:\n${rawResponse}`)) |
|
||||||
return |
|
||||||
} |
|
||||||
// update current blacklist
|
|
||||||
this.store.updateState({ phishing }) |
|
||||||
this._setupPhishingDetector(phishing) |
|
||||||
return phishing |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Initiates the updating of the local blacklist at a set interval. The update is done via this.updatePhishingList(). |
|
||||||
* Also, this method store a reference to that interval at this._phishingUpdateIntervalRef |
|
||||||
* |
|
||||||
*/ |
|
||||||
scheduleUpdates () { |
|
||||||
if (this._phishingUpdateIntervalRef) return |
|
||||||
this.updatePhishingList() |
|
||||||
this._phishingUpdateIntervalRef = setInterval(() => { |
|
||||||
this.updatePhishingList() |
|
||||||
}, POLLING_INTERVAL) |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Sets this._phishingDetector to a new PhishingDetector instance. |
|
||||||
* @see {@link https://github.com/MetaMask/eth-phishing-detect}
|
|
||||||
* |
|
||||||
* @private |
|
||||||
* @param {object} config A config object like that found at {@link https://github.com/MetaMask/eth-phishing-detect/blob/master/src/config.json}
|
|
||||||
* |
|
||||||
*/ |
|
||||||
_setupPhishingDetector (config) { |
|
||||||
this._phishingDetector = new PhishingDetector(config) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = BlacklistController |
|
File diff suppressed because it is too large
Load Diff
@ -1,56 +0,0 @@ |
|||||||
const assert = require('assert') |
|
||||||
const BlacklistController = require('../../../../app/scripts/controllers/blacklist') |
|
||||||
|
|
||||||
describe('blacklist controller', function () { |
|
||||||
let blacklistController |
|
||||||
|
|
||||||
before(() => { |
|
||||||
blacklistController = new BlacklistController() |
|
||||||
}) |
|
||||||
|
|
||||||
describe('whitelistDomain', function () { |
|
||||||
it('should add hostname to the runtime whitelist', function () { |
|
||||||
blacklistController.whitelistDomain('foo.com') |
|
||||||
assert.deepEqual(blacklistController.store.getState().whitelist, ['foo.com']) |
|
||||||
|
|
||||||
blacklistController.whitelistDomain('bar.com') |
|
||||||
assert.deepEqual(blacklistController.store.getState().whitelist, ['bar.com', 'foo.com']) |
|
||||||
}) |
|
||||||
}) |
|
||||||
|
|
||||||
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) |
|
||||||
}) |
|
||||||
it('should not flag whitelisted domain', function () { |
|
||||||
blacklistController.whitelistDomain('metamask.com') |
|
||||||
const result = blacklistController.checkForPhishing('metamask.com') |
|
||||||
assert.equal(result, false) |
|
||||||
}) |
|
||||||
}) |
|
||||||
}) |
|
Loading…
Reference in new issue