mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge branch 'master' into NewUI
This commit is contained in:
commit
d932524eaf
@ -2,6 +2,9 @@
|
||||
|
||||
## Current Master
|
||||
|
||||
- Continuously update blacklist for known phishing sites in background.
|
||||
- Automatically detect suspicious URLs too similar to common phishing targets, and blacklist them.
|
||||
|
||||
## 3.9.2 2017-7-26
|
||||
|
||||
- Fix bugs that could sometimes result in failed transactions after switching networks.
|
||||
|
@ -55,8 +55,12 @@
|
||||
},
|
||||
{
|
||||
"run_at": "document_start",
|
||||
"matches": ["http://*/*", "https://*/*"],
|
||||
"js": ["scripts/blacklister.js"]
|
||||
"matches": [
|
||||
"http://*/*",
|
||||
"https://*/*"
|
||||
],
|
||||
"js": ["scripts/blacklister.js"],
|
||||
"all_frames": true
|
||||
}
|
||||
],
|
||||
"permissions": [
|
||||
|
@ -11,6 +11,7 @@ const NotificationManager = require('./lib/notification-manager.js')
|
||||
const MetamaskController = require('./metamask-controller')
|
||||
const extension = require('extensionizer')
|
||||
const firstTimeState = require('./first-time-state')
|
||||
const isPhish = require('./lib/is-phish')
|
||||
|
||||
const STORAGE_KEY = 'metamask-config'
|
||||
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
|
||||
@ -90,8 +91,11 @@ function setupController (initState) {
|
||||
|
||||
extension.runtime.onConnect.addListener(connectRemote)
|
||||
function connectRemote (remotePort) {
|
||||
const name = remotePort.name
|
||||
var isMetaMaskInternalProcess = name === 'popup' || name === 'notification' || name === 'ui'
|
||||
if (remotePort.name === 'blacklister') {
|
||||
return checkBlacklist(remotePort)
|
||||
}
|
||||
|
||||
var isMetaMaskInternalProcess = remotePort.name === 'popup' || remotePort.name === 'notification'
|
||||
var portStream = new PortStream(remotePort)
|
||||
if (isMetaMaskInternalProcess) {
|
||||
// communication with popup
|
||||
@ -136,6 +140,27 @@ function setupController (initState) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
// Listen for new pages and return if blacklisted:
|
||||
function checkBlacklist (port) {
|
||||
const handler = handleNewPageLoad.bind(null, port)
|
||||
port.onMessage.addListener(handler)
|
||||
setTimeout(() => {
|
||||
port.onMessage.removeListener(handler)
|
||||
}, 30000)
|
||||
}
|
||||
|
||||
function handleNewPageLoad (port, message) {
|
||||
const { pageLoaded } = message
|
||||
if (!pageLoaded || !global.metamaskController) return
|
||||
|
||||
const state = global.metamaskController.getState()
|
||||
const updatedBlacklist = state.blacklist
|
||||
|
||||
if (isPhish({ updatedBlacklist, hostname: pageLoaded })) {
|
||||
port.postMessage({ 'blacklist': pageLoaded })
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Etc...
|
||||
//
|
||||
|
@ -1,41 +1,14 @@
|
||||
const levenshtein = require('fast-levenshtein')
|
||||
const blacklistedMetaMaskDomains = ['metamask.com']
|
||||
const 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']
|
||||
const extension = require('extensionizer')
|
||||
|
||||
var port = extension.runtime.connect({name: 'blacklister'})
|
||||
port.postMessage({ 'pageLoaded': window.location.hostname })
|
||||
port.onMessage.addListener(redirectIfBlacklisted)
|
||||
|
||||
// credit to @sogoiii and @409H for their help!
|
||||
// Return a boolean on whether or not a phish is detected.
|
||||
function isPhish(hostname) {
|
||||
var strCurrentTab = hostname
|
||||
|
||||
// check if the domain is part of the whitelist.
|
||||
if (whitelistedDomains && whitelistedDomains.includes(strCurrentTab)) { return false }
|
||||
|
||||
// check if the domain is part of the blacklist.
|
||||
var isBlacklisted = blacklistedDomains && blacklistedDomains.includes(strCurrentTab)
|
||||
|
||||
// check for similar values.
|
||||
var levenshteinMatched = false
|
||||
var levenshteinForm = strCurrentTab.replace(/\./g, '')
|
||||
LEVENSHTEIN_CHECKS.forEach((element) => {
|
||||
if (levenshtein.get(element, levenshteinForm) < LEVENSHTEIN_TOLERANCE) {
|
||||
levenshteinMatched = true
|
||||
}
|
||||
})
|
||||
|
||||
return isBlacklisted || levenshteinMatched
|
||||
}
|
||||
|
||||
window.addEventListener('load', function () {
|
||||
var hostnameToCheck = window.location.hostname
|
||||
if (isPhish(hostnameToCheck)) {
|
||||
// redirect to our phishing warning page.
|
||||
function redirectIfBlacklisted (response) {
|
||||
const { blacklist } = response
|
||||
const host = window.location.hostname
|
||||
if (blacklist && blacklist === host) {
|
||||
window.location.href = 'https://metamask.io/phishing.html'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = isPhish
|
||||
|
@ -1,5 +1,6 @@
|
||||
const ObservableStore = require('obs-store')
|
||||
const extend = require('xtend')
|
||||
const recentBlacklist = require('etheraddresslookup/blacklists/domains.json')
|
||||
|
||||
// every ten minutes
|
||||
const POLLING_INTERVAL = 300000
|
||||
@ -9,6 +10,7 @@ class InfuraController {
|
||||
constructor (opts = {}) {
|
||||
const initState = extend({
|
||||
infuraNetworkStatus: {},
|
||||
blacklist: recentBlacklist,
|
||||
}, opts.initState)
|
||||
this.store = new ObservableStore(initState)
|
||||
}
|
||||
@ -30,12 +32,24 @@ class InfuraController {
|
||||
})
|
||||
}
|
||||
|
||||
updateLocalBlacklist () {
|
||||
return fetch('https://api.infura.io/v1/blacklist')
|
||||
.then(response => response.json())
|
||||
.then((parsedResponse) => {
|
||||
this.store.updateState({
|
||||
blacklist: parsedResponse,
|
||||
})
|
||||
return parsedResponse
|
||||
})
|
||||
}
|
||||
|
||||
scheduleInfuraNetworkCheck () {
|
||||
if (this.conversionInterval) {
|
||||
clearInterval(this.conversionInterval)
|
||||
}
|
||||
this.conversionInterval = setInterval(() => {
|
||||
this.checkInfuraNetworkStatus()
|
||||
this.updateLocalBlacklist()
|
||||
}, POLLING_INTERVAL)
|
||||
}
|
||||
}
|
||||
|
@ -65,3 +65,4 @@ function restoreContextAfterImports () {
|
||||
console.warn('MetaMask - global.define could not be overwritten.')
|
||||
}
|
||||
}
|
||||
|
||||
|
38
app/scripts/lib/is-phish.js
Normal file
38
app/scripts/lib/is-phish.js
Normal file
@ -0,0 +1,38 @@
|
||||
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,24 +1,24 @@
|
||||
const assert = require('assert')
|
||||
const Blacklister = require('../../app/scripts/blacklister')
|
||||
|
||||
const isPhish = require('../../app/scripts/lib/is-phish')
|
||||
|
||||
describe('blacklister', function () {
|
||||
describe('#isPhish', function () {
|
||||
it('should not flag whitelisted values', function () {
|
||||
var result = Blacklister('www.metamask.io')
|
||||
var result = isPhish({ hostname: 'www.metamask.io' })
|
||||
assert(!result)
|
||||
})
|
||||
it('should flag explicit values', function () {
|
||||
var result = Blacklister('metamask.com')
|
||||
var result = isPhish({ hostname: 'metamask.com' })
|
||||
assert(result)
|
||||
})
|
||||
it('should flag levenshtein values', function () {
|
||||
var result = Blacklister('metmask.io')
|
||||
var result = isPhish({ hostname: 'metmask.com' })
|
||||
assert(result)
|
||||
})
|
||||
it('should not flag not-even-close values', function () {
|
||||
var result = Blacklister('example.com')
|
||||
var result = isPhish({ hostname: 'example.com' })
|
||||
assert(!result)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user