Merge pull request #5406 from whymarrh/bypass-phishing-warning

Allow users to bypass phishing warning
feature/default_network_editable
Dan Finlay 6 years ago committed by GitHub
commit 8dc8fd0903
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      app/phishing.html
  2. 6
      app/scripts/contentscript.js
  3. 22
      app/scripts/controllers/blacklist.js
  4. 11
      app/scripts/metamask-controller.js
  5. 56
      app/scripts/phishing-detect.js
  6. 15
      test/unit/app/controllers/blacklist-controller-test.js

@ -3,7 +3,7 @@
<html>
<head>
<title>Dangerous Website Warning</title>
<title>Ethereum Phishing Detection - MetMask</title>
<style>
body {
@ -24,6 +24,8 @@
a {
color: white;
cursor: pointer;
text-decoration: underline;
}
</style>
@ -57,7 +59,11 @@
<p>This is because the site tested positive on the <a href="https://github.com/metamask/eth-phishing-detect">Ethereum Phishing Detector</a>. This includes outright malicious websites and legitimate websites that have been compromised by a malicious actor.</p>
<p id="esdbLink"></p>
<p>You can turn MetaMask off to interact with this site, but it is advised not to.</p>
<p>If you think this domain is incorrectly flagged or if a blocked legitimate website has resolved its security issues, <a href="https://github.com/metamask/eth-phishing-detect/issues/new">please file an issue</a>.</p>
<p>
If you think this domain is incorrectly flagged or if a blocked legitimate website has resolved its security issues,
<a href="https://github.com/metamask/eth-phishing-detect/issues/new">please file an issue</a>. If you believe this website
is safe and understand the risks involved, you can <a id="unsafe-continue">visit this unsafe website at your own risk</a>.
</p>
</div>
</body>

@ -1,6 +1,7 @@
const fs = require('fs')
const path = require('path')
const pump = require('pump')
const querystring = require('querystring')
const LocalMessageDuplexStream = require('post-message-stream')
const PongStream = require('ping-pong-stream/pong')
const ObjectMultiplex = require('obj-multiplex')
@ -199,5 +200,8 @@ function blacklistedDomainCheck () {
function redirectToPhishingWarning () {
console.log('MetaMask - routing to Phishing Warning component')
const extensionURL = extension.runtime.getURL('phishing.html')
window.location.href = extensionURL + '#' + window.location.hostname
window.location.href = `${extensionURL}#${querystring.stringify({
hostname: window.location.hostname,
href: window.location.href,
})}`
}

@ -29,6 +29,7 @@ class BlacklistController {
constructor (opts = {}) {
const initState = extend({
phishing: PHISHING_DETECTION_CONFIG,
whitelist: [],
}, opts.initState)
this.store = new ObservableStore(initState)
// phishing detector
@ -38,6 +39,21 @@ class BlacklistController {
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
*
@ -48,6 +64,12 @@ class BlacklistController {
*/
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
}

@ -387,6 +387,9 @@ module.exports = class MetamaskController extends EventEmitter {
setAccountLabel: nodeify(preferencesController.setAccountLabel, preferencesController),
setFeatureFlag: nodeify(preferencesController.setFeatureFlag, preferencesController),
// BlacklistController
whitelistPhishingDomain: this.whitelistPhishingDomain.bind(this),
// AddressController
setAddressBook: nodeify(addressBookController.setAddressBook, addressBookController),
@ -1541,4 +1544,12 @@ module.exports = class MetamaskController extends EventEmitter {
}
}
}
/**
* Adds a domain to the {@link BlacklistController} whitelist
* @param {string} hostname the domain to whitelist
*/
whitelistPhishingDomain (hostname) {
return this.blacklistController.whitelistDomain(hostname)
}
}

@ -1,5 +1,59 @@
window.onload = function() {
if (window.location.pathname === '/phishing.html') {
document.getElementById('esdbLink').innerHTML = '<b>To read more about this scam, navigate to: <a href="https://etherscamdb.info/domain/' + window.location.hash.substring(1) + '"> https://etherscamdb.info/domain/' + window.location.hash.substring(1) + '</a></b>'
const {hostname} = parseHash()
document.getElementById('esdbLink').innerHTML = '<b>To read more about this scam, navigate to: <a href="https://etherscamdb.info/domain/' + hostname + '"> https://etherscamdb.info/domain/' + hostname + '</a></b>'
}
}
const querystring = require('querystring')
const dnode = require('dnode')
const { EventEmitter } = require('events')
const PortStream = require('extension-port-stream')
const extension = require('extensionizer')
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
const { getEnvironmentType } = require('./lib/util')
const ExtensionPlatform = require('./platforms/extension')
document.addEventListener('DOMContentLoaded', start)
function start () {
const windowType = getEnvironmentType(window.location.href)
global.platform = new ExtensionPlatform()
global.METAMASK_UI_TYPE = windowType
const extensionPort = extension.runtime.connect({ name: windowType })
const connectionStream = new PortStream(extensionPort)
const mx = setupMultiplex(connectionStream)
setupControllerConnection(mx.createStream('controller'), (err, metaMaskController) => {
if (err) {
return
}
const suspect = parseHash()
const unsafeContinue = () => {
window.location.href = suspect.href
}
const continueLink = document.getElementById('unsafe-continue')
continueLink.addEventListener('click', () => {
metaMaskController.whitelistPhishingDomain(suspect.hostname)
unsafeContinue()
})
})
}
function setupControllerConnection (connectionStream, cb) {
const eventEmitter = new EventEmitter()
const accountManagerDnode = dnode({
sendUpdate (state) {
eventEmitter.emit('update', state)
},
})
connectionStream.pipe(accountManagerDnode).pipe(connectionStream)
accountManagerDnode.once('remote', (accountManager) => cb(null, accountManager))
}
function parseHash () {
const hash = window.location.hash.substring(1)
return querystring.parse(hash)
}

@ -8,6 +8,16 @@ describe('blacklist controller', function () {
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')
@ -37,5 +47,10 @@ describe('blacklist controller', 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…
Cancel
Save