Implemented command. Implemented filter.
This commit is contained in:
parent
6a88043e9c
commit
ddf74ba69c
14
README.md
14
README.md
|
@ -20,5 +20,19 @@ embark-mythx:
|
|||
embark-mythx: MythX analysis found vulnerabilities.
|
||||
```
|
||||
|
||||
# Installation
|
||||
|
||||
Add `embark-mythx` to the `plugins` section in your `embark.json`. To have the plugin permanently ignore one or multiple contracts, add them as array `ignore` to the configuration:
|
||||
|
||||
```
|
||||
"plugins": {
|
||||
"embark-mythx": {
|
||||
"ignore": ["Ownable", "Migrations"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Options
|
||||
|
||||
`--full`, `-f` -- run full analysis instead of quick.
|
||||
`--debug`, `-d` -- print additional output.
|
||||
|
|
22
index.js
22
index.js
|
@ -48,15 +48,14 @@ module.exports = function(embark) {
|
|||
//embark.logger.info("result", result)
|
||||
|
||||
if (returnCode === 0) {
|
||||
return callback(null, "returnCode: " + returnCode)
|
||||
return callback(null, "MythX analysis found no vulnerabilities.")
|
||||
} else if (returnCode === 1) {
|
||||
embark.logger.error("\nMythX analysis found vulnerabilities.")
|
||||
return callback()
|
||||
} else {
|
||||
//TODO: Figure out how to use error with callback properly.
|
||||
return callback("MythX analysis found vulnerabilities!", null)
|
||||
} else if (returnCode === 2) {
|
||||
return callback("Internal MythX error encountered.", null)
|
||||
} else {
|
||||
return callback(new Error("\nUnexpected Error: return value of `analyze` should be either 0 or 1."), null)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
embark.logger.error("error", e)
|
||||
return callback(e, "ERR: " + e.message)
|
||||
|
@ -100,7 +99,7 @@ module.exports = function(embark) {
|
|||
//embark.logger.info('cmdName.length === 1', cmdName.length === 1)
|
||||
return (Array.isArray(cmdName) &&
|
||||
cmdName[0] === 'verify' &&
|
||||
cmdName[1] != 'status' &&
|
||||
cmdName[1] == 'status' &&
|
||||
cmdName.length == 3)
|
||||
},
|
||||
usage: "verify status <uuid>",
|
||||
|
@ -108,17 +107,19 @@ module.exports = function(embark) {
|
|||
//embark.logger.info("verify status running")
|
||||
//embark.logger.info("embark.logger", JSON.stringify(embark.logger))
|
||||
|
||||
let cfg = parseOptions(cmd)
|
||||
const cmdName = cmd.match(/".*?"|\S+/g)
|
||||
|
||||
//embark.logger.info('cmd', cmd)
|
||||
//embark.logger.info('cfg', JSON.stringify(cfg))
|
||||
try {
|
||||
const returnCode = await mythx.getStatus(cfg, embark)
|
||||
const returnCode = await mythx.getStatus(cmdName[2], embark)
|
||||
//embark.logger.info("result", result)
|
||||
|
||||
if (returnCode === 0) {
|
||||
return callback(null, "returnCode: " + returnCode)
|
||||
} else if (returnCode === 1) {
|
||||
embark.logger.error("MythX analysis found vulnerabilities.")
|
||||
//embark.logger.error("MythX analysis found vulnerabilities.")
|
||||
//TODO: Fix reporting
|
||||
return callback()
|
||||
} else {
|
||||
//TODO: Figure out how to use error with callback properly.
|
||||
|
@ -141,6 +142,7 @@ module.exports = function(embark) {
|
|||
{ name: 'debug', alias: 'd', type: Boolean },
|
||||
{ name: 'no-cache-lookup', alias: 'c', type: Boolean },
|
||||
{ name: 'limit', alias: 'l', type: Number },
|
||||
{ name: 'initial-delay', alias: 'i', type: Number },
|
||||
{ name: 'contracts', type: String, multiple: true, defaultOption: true }
|
||||
]
|
||||
|
||||
|
|
|
@ -321,7 +321,7 @@ function doReport(config, objects, errors, notAnalyzedContracts) {
|
|||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
ret = 1;
|
||||
ret = 2;
|
||||
config.logger.error('Internal MythX errors encountered:'.red);
|
||||
errors.forEach(err => {
|
||||
config.logger.error(err.error || err);
|
||||
|
|
53
mythx.js
53
mythx.js
|
@ -2,6 +2,7 @@ require('dotenv').config()
|
|||
|
||||
const armlet = require('armlet')
|
||||
const fs = require('fs')
|
||||
const yaml = require('js-yaml');
|
||||
const mythXUtil = require('./lib/mythXUtil');
|
||||
const asyncPool = require('tiny-async-pool');
|
||||
const { MythXIssues, doReport } = require('./lib/issues2eslint');
|
||||
|
@ -50,19 +51,25 @@ async function analyse(contracts, cfg, embark) {
|
|||
toSubmit.contracts = {}
|
||||
for (let [filename, contractObjects] of Object.entries(contracts.contracts)) {
|
||||
for (let [contractName, contract] of Object.entries(contractObjects)) {
|
||||
if (cfg.contracts.indexOf(contractName) >= 0) {
|
||||
if (cfg.contracts.indexOf(contractName) >= 0 && embark.pluginConfig.ignore.indexOf(contractName) == -1) {
|
||||
//console.log("Adding to submit", contractName, contractObjects)
|
||||
if(!toSubmit.contracts[filename]) {
|
||||
toSubmit.contracts[filename] = {}
|
||||
}
|
||||
toSubmit.contracts[filename][contractName] = contract ;
|
||||
toSubmit.contracts[filename][contractName] = contract;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toSubmit = contracts
|
||||
}
|
||||
|
||||
|
||||
// Stop here if no contracts are left
|
||||
if(Object.keys(toSubmit.contracts).length === 0) {
|
||||
embark.logger.info("No contracts to submit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//embark.logger.info("toSubmit", toSubmit)
|
||||
const submitObjects = mythXUtil.buildRequestData(toSubmit)
|
||||
|
||||
|
@ -77,15 +84,13 @@ async function analyse(contracts, cfg, embark) {
|
|||
return result
|
||||
}
|
||||
|
||||
async function getStatus(cfg, embark) {
|
||||
async function getStatus(uuid, embark) {
|
||||
|
||||
//embark.logger.debug("embark.config", embark.config)
|
||||
|
||||
//console.log("embark.logger", embark.logger)
|
||||
//console.log("JSON.stringify(embark.logger)", JSON.stringify(embark.logger))
|
||||
//embark.logger.info("typeof embark.logger", typeof embark.logger)
|
||||
cfg.logger = embark.logger
|
||||
//embark.logger.info("embark", JSON.stringify(embark))
|
||||
|
||||
// Connect to MythX via armlet
|
||||
const armletClient = new armlet.Client(
|
||||
|
@ -95,14 +100,12 @@ async function getStatus(cfg, embark) {
|
|||
ethAddress: process.env.MYTHX_ETH_ADDRESS,
|
||||
})
|
||||
|
||||
if (cfg.uuid) {
|
||||
try {
|
||||
const results = await armletClient.getIssues(config.uuid);
|
||||
return ghettoReport(embark.logger.info, results);
|
||||
} catch (err) {
|
||||
embark.logger.warn(err);
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
const results = await armletClient.getIssues(uuid);
|
||||
return ghettoReport(embark.logger.info, results);
|
||||
} catch (err) {
|
||||
embark.logger.warn(err);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +115,7 @@ const doAnalysis = async (armletClient, config, contracts, contractNames = null,
|
|||
|
||||
const timeout = (config.timeout || 300) * 1000;
|
||||
const initialDelay = ('initial-delay' in config) ? config['initial-delay'] * 1000 : undefined;
|
||||
const cacheLookup = ('cache-lookup' in config) ? config['cache-lookup'] : true;
|
||||
const noCacheLookup = ('no-cache-lookup' in config) ? config['no-cache-lookup'] : true;
|
||||
|
||||
const results = await asyncPool(limit, contracts, async buildObj => {
|
||||
|
||||
|
@ -120,34 +123,28 @@ const doAnalysis = async (armletClient, config, contracts, contractNames = null,
|
|||
|
||||
let analyzeOpts = {
|
||||
clientToolName: 'embark-mythx',
|
||||
noCacheLookup: !cacheLookup,
|
||||
noCacheLookup,
|
||||
timeout,
|
||||
initialDelay
|
||||
};
|
||||
|
||||
analyzeOpts.data = mythXUtil.cleanAnalyzeDataEmptyProps(obj.buildObj, config.debug, config.logger.debug);
|
||||
analyzeOpts.data.analysisMode = analyzeOpts.mode || 'quick';
|
||||
analyzeOpts.data.analysisMode = config.full ? "full" : "quick";
|
||||
if (config.debug > 1) {
|
||||
config.logger.debug("analyzeOpts: " + `${util.inspect(analyzeOpts, {depth: null})}`);
|
||||
}
|
||||
|
||||
// request analysis to armlet.
|
||||
try {
|
||||
config.logger.info("Submitting '" + obj.contractName + "' for analysis...")
|
||||
const armletResult = await armletClient.analyzeWithStatus(analyzeOpts);
|
||||
config.logger.info("Submitting '" + obj.contractName + "' for " + analyzeOpts.data.analysisMode + " analysis...")
|
||||
const {issues, status} = await armletClient.analyzeWithStatus(analyzeOpts);
|
||||
console.log("after analyze call")
|
||||
//config.logger.info("armletResult", JSON.stringify(armletResult))
|
||||
const {issues, status} = armletResult
|
||||
//config.logger.info("issues", issues)
|
||||
//config.logger.info("status", status)
|
||||
obj.uuid = status.uuid;
|
||||
if (config.debug) {
|
||||
config.logger.debug(`${analyzeOpts.data.contractName}: UUID is ${status.uuid}`);
|
||||
if (config.debug > 1) {
|
||||
config.logger.debug("issues: " + `${util.inspect(issues, {depth: null})}`);
|
||||
config.logger.debug("status: " + `${util.inspect(status, {depth: null})}`);
|
||||
}
|
||||
}
|
||||
|
||||
config.logger.info(`${analyzeOpts.data.contractName}: UUID is ${status.uuid}`);
|
||||
|
||||
if (status.status === 'Error') {
|
||||
return [status, null];
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue