mirror of
https://github.com/embarklabs/embark-mythx.git
synced 2025-02-21 06:38:09 +00:00
Fixing help string; cleanup
This commit is contained in:
parent
9f7a38053a
commit
0358adcf0a
@ -2,7 +2,14 @@ Status Embark plugin for MythX.
|
||||
|
||||
# QuickStart
|
||||
|
||||
Run `verify [options] [contracts]` in the Embark console. When the call returns, it will look something like this:
|
||||
0. Create a `.env` file in the root of your project and provide your MythX login information.
|
||||
|
||||
```
|
||||
MYTHX_ETH_ADDRESS="<mythx-address>"
|
||||
MYTHX_PASSWORD="<password>"
|
||||
```
|
||||
|
||||
1. Run `verify [options] [contracts]` in the Embark console. When the call returns, it will look something like this:
|
||||
|
||||
```
|
||||
Embark (development) > verify
|
||||
|
59
index.js
59
index.js
@ -7,18 +7,13 @@ module.exports = function(embark) {
|
||||
|
||||
// Register for compilation results
|
||||
embark.events.on("contracts:compiled:solc", (res) => {
|
||||
//console.log("contracts:compiled:solc", JSON.stringify(res));
|
||||
contracts = res;
|
||||
});
|
||||
|
||||
embark.registerConsoleCommand({
|
||||
description: "Run MythX analysis",
|
||||
matches: (cmd) => {
|
||||
//embark.logger.info('cmd', cmd)
|
||||
const cmdName = cmd.match(/".*?"|\S+/g)
|
||||
//embark.logger.info("cmdName", cmdName)
|
||||
//embark.logger.info('cmdName.length === 1', cmdName.length === 1)
|
||||
//embark.logger.info("eh?")
|
||||
return (Array.isArray(cmdName) &&
|
||||
cmdName[0] === 'verify' &&
|
||||
cmdName[1] != 'help' &&
|
||||
@ -27,25 +22,16 @@ module.exports = function(embark) {
|
||||
},
|
||||
usage: "verify [options] [contracts]",
|
||||
process: async (cmd, callback) => {
|
||||
//embark.logger.info("cmd", cmd)
|
||||
//embark.logger.info("verifying...")
|
||||
|
||||
const cmdName = cmd.match(/".*?"|\S+/g)
|
||||
// Remove first element, as we know it's the command
|
||||
cmdName.shift()
|
||||
|
||||
//embark.logger.info("embark.logger", JSON.stringify(embark.logger))
|
||||
|
||||
//console.log("option object", JSON.stringify({ "argv": cmdName }))
|
||||
let cfg = parseOptions({ "argv": cmdName })
|
||||
|
||||
//embark.logger.info('cmd', cmdName)
|
||||
//embark.logger.info('cfg', JSON.stringify(cfg))
|
||||
|
||||
try {
|
||||
embark.logger.info("Running MythX analysis in background.")
|
||||
const returnCode = await mythx.analyse(contracts, cfg, embark)
|
||||
//embark.logger.info("result", result)
|
||||
|
||||
if (returnCode === 0) {
|
||||
return callback(null, "MythX analysis found no vulnerabilities.")
|
||||
@ -57,7 +43,6 @@ module.exports = function(embark) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -66,37 +51,41 @@ module.exports = function(embark) {
|
||||
embark.registerConsoleCommand({
|
||||
description: "Help",
|
||||
matches: (cmd) => {
|
||||
//embark.logger.info('cmd', cmd)
|
||||
const cmdName = cmd.match(/".*?"|\S+/g)
|
||||
//embark.logger.info('cmdName', cmdName)
|
||||
//embark.logger.info("cmdName[0] === 'verify' && cmdName[1] === 'help'", cmdName[0] === 'verify' && cmdName[1] === 'help')
|
||||
return (Array.isArray(cmdName) &&
|
||||
(cmdName[0] === 'verify' &&
|
||||
cmdName[1] === 'help'))
|
||||
},
|
||||
usage: "verify help",
|
||||
process: (cmd, callback) => {
|
||||
embark.logger.info("verify help running")
|
||||
return callback(null, help())
|
||||
}
|
||||
})
|
||||
|
||||
function help() {
|
||||
return (
|
||||
"Usage: ...\n" +
|
||||
"Usage:\n" +
|
||||
"\tverify [--full] [--debug] [--no-cache-lookup] [--limit] [--initial-delay] [<contracts>]\n" +
|
||||
"\tverify status <uuid>\n" +
|
||||
"\tverify help\n" +
|
||||
"\n" +
|
||||
"Commands:\n" +
|
||||
"\thelp\t\tThis help."
|
||||
"Options:\n" +
|
||||
"\t--full\t\t\tPerform full rather than quick analysis.\n" +
|
||||
"\t--debug\t\t\tAdditional debug output.\n" +
|
||||
"\t--no-cache-lookup\tSkip MythX-side cache lookup of report.\n" +
|
||||
"\t--limit\t\t\tMaximum number of concurrent analyses.\n" +
|
||||
"\t--initial-delay\t\tTime in seconds before first analysis status check.\n" +
|
||||
"\n" +
|
||||
"\t[<contracts>]\t\tList of contracts to submit for analysis (default: all).\n" +
|
||||
"\tstatus <uuid>\t\tRetrieve analysis status for given MythX UUID.\n" +
|
||||
"\thelp\t\t\tThis help.\n"
|
||||
)
|
||||
}
|
||||
|
||||
embark.registerConsoleCommand({
|
||||
description: "Check MythX analysis status",
|
||||
matches: (cmd) => {
|
||||
//embark.logger.info('cmd', cmd)
|
||||
const cmdName = cmd.match(/".*?"|\S+/g)
|
||||
//embark.logger.info("cmdName", cmdName)
|
||||
//embark.logger.info('cmdName.length === 1', cmdName.length === 1)
|
||||
return (Array.isArray(cmdName) &&
|
||||
cmdName[0] === 'verify' &&
|
||||
cmdName[1] == 'status' &&
|
||||
@ -104,39 +93,25 @@ module.exports = function(embark) {
|
||||
},
|
||||
usage: "verify status <uuid>",
|
||||
process: async (cmd, callback) => {
|
||||
//embark.logger.info("verify status running")
|
||||
//embark.logger.info("embark.logger", JSON.stringify(embark.logger))
|
||||
|
||||
const cmdName = cmd.match(/".*?"|\S+/g)
|
||||
|
||||
//embark.logger.info('cmd', cmd)
|
||||
//embark.logger.info('cfg', JSON.stringify(cfg))
|
||||
try {
|
||||
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.")
|
||||
//TODO: Fix reporting
|
||||
return callback()
|
||||
} else {
|
||||
//TODO: Figure out how to use error with callback properly.
|
||||
return callback(new Error("Unexpected 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)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function parseOptions(options) {
|
||||
|
||||
//console.log("options", JSON.stringify(options))
|
||||
|
||||
const optionDefinitions = [
|
||||
{ name: 'full', alias: 'f', type: Boolean },
|
||||
{ name: 'debug', alias: 'd', type: Boolean },
|
||||
@ -148,14 +123,10 @@ module.exports = function(embark) {
|
||||
|
||||
const parsed = commandLineArgs(optionDefinitions, options)
|
||||
|
||||
//console.log("parsed", JSON.stringify(parsed))
|
||||
//console.log("parsed.contracts", parsed.contracts)
|
||||
//console.log("parsed.full", parsed.full)
|
||||
|
||||
if(parsed.full) {
|
||||
parsed.analysisMode = "full"
|
||||
} else {
|
||||
parsed.analysisMode = "full"
|
||||
parsed.analysisMode = "quick"
|
||||
}
|
||||
|
||||
return parsed
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
const path = require('path');
|
||||
const assert = require('assert');
|
||||
const SourceMappingDecoder = require(
|
||||
'remix-lib/src/sourceMappingDecoder');
|
||||
const SourceMappingDecoder = require('remix-lib/src/sourceMappingDecoder');
|
||||
const srcmap = require('./srcmap');
|
||||
const mythx = require('./mythXUtil');
|
||||
|
||||
@ -69,7 +68,6 @@ class MythXIssues {
|
||||
constructor(buildObj, config) {
|
||||
this.issues = [];
|
||||
this.logs = [];
|
||||
//console.log("mythx", JSON.stringify(mythx))
|
||||
this.buildObj = mythx.embark2MythXJSON(buildObj);
|
||||
this.debug = config.debug;
|
||||
this.logger = config.logger;
|
||||
@ -79,7 +77,6 @@ class MythXIssues {
|
||||
this.offset2InstNum = srcmap.makeOffset2InstNum(this.buildObj.deployedBytecode);
|
||||
this.contractName = buildObj.contractName;
|
||||
this.sourceMappingDecoder = new SourceMappingDecoder();
|
||||
//console.log("buildObj", buildObj)
|
||||
this.asts = this.mapAsts(this.buildObj.sources);
|
||||
this.lineBreakPositions = this.mapLineBreakPositions(this.sourceMappingDecoder, this.buildObj.sources);
|
||||
}
|
||||
@ -121,12 +118,10 @@ class MythXIssues {
|
||||
|
||||
mapAsts (sources) {
|
||||
const result = {};
|
||||
//console.log("sources", JSON.stringify(sources))
|
||||
Object.entries(sources).forEach(([ sourcePath, { ast } ]) => {
|
||||
result[sourcePath] = ast;
|
||||
});
|
||||
|
||||
//console.log("mapAsts output: ", JSON.stringify(result))
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ const srcmap = require('./srcmap');
|
||||
|
||||
const getContractFiles = directory => {
|
||||
let files = fs.readdirSync(directory)
|
||||
console.log("files", files)
|
||||
files = files.filter(f => f !== "ENSRegistry.json" && f !== "FIFSRegistrar.json" && f !== "Resolver.json");
|
||||
return files.map(f => path.join(directory, f))
|
||||
};
|
||||
@ -33,8 +32,6 @@ const getNotFoundContracts = (allContractNames, foundContracts) => {
|
||||
|
||||
const buildRequestData = contractObjects => {
|
||||
|
||||
//console.log("contractObjects", JSON.stringify(contractObjects))
|
||||
|
||||
const { sources, compiler } = contractObjects;
|
||||
let allContracts = [];
|
||||
|
||||
@ -48,12 +45,9 @@ const buildRequestData = contractObjects => {
|
||||
|
||||
Object.keys(contractObjects.contracts).forEach(function(fileKey, index) {
|
||||
const contractFile = contractObjects.contracts[fileKey];
|
||||
//const sources = contractObjects.sources[fileKey];
|
||||
|
||||
|
||||
Object.keys(contractFile).forEach(function(contractKey, index) {
|
||||
const contractJSON = contractFile[contractKey]
|
||||
//console.log("goes in", [sourcePath, data])
|
||||
const contract = {
|
||||
contractName: contractKey,
|
||||
bytecode: contractJSON.evm.bytecode.object,
|
||||
@ -64,7 +58,6 @@ const buildRequestData = contractObjects => {
|
||||
sourcePath: fileKey
|
||||
};
|
||||
|
||||
//console.log("comes out", contract)
|
||||
allContracts = allContracts.concat(contract);
|
||||
});
|
||||
});
|
||||
@ -102,7 +95,6 @@ const embark2MythXJSON = function(embarkJSON, toolId = 'embark-mythx') {
|
||||
toolId
|
||||
}
|
||||
|
||||
//console.log("mythXJSON", JSON.stringify(mythXJSON))
|
||||
return mythXJSON;
|
||||
};
|
||||
|
||||
|
59
mythx.js
59
mythx.js
@ -7,31 +7,31 @@ const mythXUtil = require('./lib/mythXUtil');
|
||||
const asyncPool = require('tiny-async-pool');
|
||||
const { MythXIssues, doReport } = require('./lib/issues2eslint');
|
||||
|
||||
const defaultAnalyzeRateLimit = 4
|
||||
const defaultConcurrentAnalyses = 4
|
||||
|
||||
async function analyse(contracts, cfg, 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))
|
||||
|
||||
// Set analysis parameters
|
||||
const limit = cfg.limit || defaultAnalyzeRateLimit
|
||||
const limit = cfg.limit || defaultConcurrentAnalyses
|
||||
|
||||
if (isNaN(limit)) {
|
||||
embark.logger.info(`limit parameter should be a number; got ${limit}.`)
|
||||
return 1
|
||||
}
|
||||
if (limit < 0 || limit > defaultAnalyzeRateLimit) {
|
||||
embark.logger.info(`limit should be between 0 and ${defaultAnalyzeRateLimit}; got ${limit}.`)
|
||||
if (limit < 0 || limit > defaultConcurrentAnalyses) {
|
||||
embark.logger.info(`limit should be between 0 and ${defaultConcurrentAnalyses}.`)
|
||||
return 1
|
||||
}
|
||||
|
||||
// Connect to MythX via armlet
|
||||
if(!process.env.MYTHX_ETH_ADDRESS || !process.env.MYTHX_PASSWORD) {
|
||||
embark.logger.error("Environment variables 'MYTHX_ETH_ADDRESS' and 'MYTHX_PASSWORD' not found. Continuing in evaluation mode.")
|
||||
process.env.MYTHX_ETH_ADDRESS = "0x0000000000000000000000000000000000000000"
|
||||
process.env.MYTHX_PASSWORD = "trial"
|
||||
}
|
||||
|
||||
const armletClient = new armlet.Client(
|
||||
{
|
||||
clientToolName: "embark-mythx",
|
||||
@ -39,38 +39,25 @@ async function analyse(contracts, cfg, embark) {
|
||||
ethAddress: process.env.MYTHX_ETH_ADDRESS,
|
||||
})
|
||||
|
||||
|
||||
//Check contract names provided in options are respected
|
||||
//embark.logger.info("contracts", contracts)
|
||||
embark.logger.info("cfg.contracts", cfg.contracts)
|
||||
|
||||
//console.log("embark.pluginConfig.ignore", embark.pluginConfig.ignore)
|
||||
// Filter contracts based on parameter choice
|
||||
|
||||
let toSubmit = { "contracts": {}, "sources": contracts.sources };
|
||||
if(!("ignore" in embark.pluginConfig)) {
|
||||
embark.pluginConfig.ignore = []
|
||||
}
|
||||
|
||||
console.log("embark.pluginConfig.ignore", JSON.stringify(embark.pluginConfig.ignore))
|
||||
//console.log("cfg.contracts", cfg.contracts)
|
||||
for (let [filename, contractObjects] of Object.entries(contracts.contracts)) {
|
||||
for (let [contractName, contract] of Object.entries(contractObjects)) {
|
||||
if(!("contracts" in cfg)) {
|
||||
if (embark.pluginConfig.ignore.indexOf(contractName) == -1) {
|
||||
//console.log("Adding to submit", contractName, contractObjects)
|
||||
if(!toSubmit.contracts[filename]) {
|
||||
toSubmit.contracts[filename] = {}
|
||||
//toSubmit.sources[filename] = contracts.sources[filename]
|
||||
}
|
||||
toSubmit.contracts[filename][contractName] = contract;
|
||||
}
|
||||
} else {
|
||||
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.sources[filename] = contracts.sources[filename]
|
||||
}
|
||||
toSubmit.contracts[filename][contractName] = contract;
|
||||
}
|
||||
@ -78,39 +65,21 @@ async function analyse(contracts, cfg, embark) {
|
||||
}
|
||||
}
|
||||
|
||||
//console.log("toSubmit", JSON.stringify(toSubmit))
|
||||
//console.log("contracts", JSON.stringify(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)
|
||||
|
||||
console.log("submitObjects", JSON.stringify(submitObjects))
|
||||
|
||||
//return 0
|
||||
const { objects, errors } = await doAnalysis(armletClient, cfg, submitObjects, null, limit)
|
||||
|
||||
//console.log("objects", JSON.stringify(objects))
|
||||
//embark.logger.info("errors", errors)
|
||||
|
||||
const result = doReport(cfg, objects, errors)
|
||||
//embark.logger.info("result", result)
|
||||
return result
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
// Connect to MythX via armlet
|
||||
const armletClient = new armlet.Client(
|
||||
{
|
||||
@ -130,8 +99,6 @@ async function getStatus(uuid, embark) {
|
||||
|
||||
const doAnalysis = async (armletClient, config, contracts, contractNames = null, limit) => {
|
||||
|
||||
//config.logger.info("\ncontracts", contracts)
|
||||
|
||||
const timeout = (config.timeout || 300) * 1000;
|
||||
const initialDelay = ('initial-delay' in config) ? config['initial-delay'] * 1000 : undefined;
|
||||
const noCacheLookup = ('no-cache-lookup' in config) ? config['no-cache-lookup'] : true;
|
||||
@ -147,8 +114,6 @@ const doAnalysis = async (armletClient, config, contracts, contractNames = null,
|
||||
initialDelay
|
||||
};
|
||||
|
||||
console.log("obj", JSON.stringify(obj))
|
||||
|
||||
analyzeOpts.data = mythXUtil.cleanAnalyzeDataEmptyProps(obj.buildObj, config.debug, config.logger.debug);
|
||||
analyzeOpts.data.analysisMode = config.full ? "full" : "quick";
|
||||
if (config.debug > 1) {
|
||||
@ -162,8 +127,6 @@ const doAnalysis = async (armletClient, config, contracts, contractNames = null,
|
||||
const {issues, status} = await armletClient.analyzeWithStatus(analyzeOpts);
|
||||
obj.uuid = status.uuid;
|
||||
|
||||
console.log("uuid", obj.uuid)
|
||||
|
||||
if (status.status === 'Error') {
|
||||
return [status, null];
|
||||
} else {
|
||||
@ -191,8 +154,6 @@ const doAnalysis = async (armletClient, config, contracts, contractNames = null,
|
||||
}
|
||||
});
|
||||
|
||||
//console.log("results", JSON.stringify(results))
|
||||
|
||||
return results.reduce((accum, curr) => {
|
||||
const [ err, obj ] = curr;
|
||||
if (err) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user