diff --git a/package.json b/package.json index cdc882d..2ba476a 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,8 @@ "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.6.0", "eslint-plugin-standard": "^3.0.1", + "ethereumjs-util": "^5.2.0", + "husky": "^1.0.0-rc.10", "jest": "^22.2.1", "smee-client": "^1.0.1", "standard": "^10.0.3" @@ -51,5 +53,10 @@ "unfurl", "wip" ] + }, + "husky": { + "hooks": { + "pre-push": "git fetch --no-tags && node scripts/pre-push --loglevel warn ${HUSKY_GIT_STDIN}" + } } } diff --git a/scripts/pre-push b/scripts/pre-push new file mode 100644 index 0000000..ca60f1e --- /dev/null +++ b/scripts/pre-push @@ -0,0 +1,82 @@ +#!/usr/bin/env node +// requirements +const ethereumjs = require('ethereumjs-util') +const https = require('https') +const exec = require('child_process').exec +// constants +const host = 'https://api.etherscan.io/api?module=account&action=balancemulti&address=' +// variables +var foundPrivateKeys = [] +var formatedKeys = [] +var rawKeysFound = [] +var keyFound = false +var originSHA = process.env.HUSKY_GIT_STDIN.split(/\s+/)[3] +var masterSHA = process.env.HUSKY_GIT_STDIN.split(/\s+/)[1] +// start script +console.log('\x1b[1m', 'Checking for possible private keys with balance...\n', '\x1b[0m') +// setup shell script command function +var result = function (command, cb) { + exec(command, function (err, stdout, stderr) { + if (err != null) { + return cb(new Error(err), null) + } else if (typeof (stderr) !== 'string') { + return cb(new Error(stderr), null) + } else { + return cb(null, stdout) + } + }) +} +// get git to return files that have been altered +result('git diff ' + masterSHA + ' ' + originSHA + ' --name-only', function (err, response) { + if (!err && response !== '') { + // look for possible private keys + let splitResult = response.replace(/\r?\n|\r/g, ' ').split(' ').join(' ') + result('grep -E -- "([0-9A-Fa-f][^OIl]){32}" ' + splitResult, function (err, response) { + if (!err) { + foundPrivateKeys = response.replace(/[^0-9A-Fa-f]/g, ' ').split(' ') + + for (var i in foundPrivateKeys) { + if (foundPrivateKeys[i].length === 64) { + rawKeysFound.push(foundPrivateKeys[i]) + formatedKeys.push(ethereumjs.bufferToHex(ethereumjs.privateToAddress(ethereumjs.toBuffer('0x' + foundPrivateKeys[i])))) + } + } + // make api call to etherscan to check balance + https.get(host + formatedKeys.toString() + '&tag=latest&apikey=YourApiKeyToken', (resp) => { + let data = '' + resp.on('data', (chunk) => { + data += chunk + }) + resp.on('end', () => { + let returnedKeys = (JSON.parse(data).result) + for (var i in returnedKeys) { + if (returnedKeys[i].balance > 0) { + console.log('Private key found: \x1b[41m%s\x1b[0m', rawKeysFound[i], ' with balance of: ', returnedKeys[i].balance / Math.pow(10, 18)) + if (!keyFound) keyFound = true + } + } + + if (!keyFound) { + console.log('\x1b[32m', 'No private keys with balance found...\n', '\x1b[0m') + process.exit(0) + } else { + console.log('\x1b[33m', '\nPrivate key(s) with balance found: to commit anyway use command "git push --no-verify"\n', '\x1b[0m') + process.exit(1) + } + }) + }).on('error', (err) => { + console.log('Error: ' + err.message) + process.exit(2) + }) + } else { + console.log('\x1b[32m', 'No private keys found in commits\n', '\x1b[0m') + process.exit(0) + } + }) + } else { + if (response === '') { + console.log('No changed files found.') + } else { console.log('Error: ' + err) } + process.exit(2) + } +})