A Deep Dive into the MythX Smart Contract Security Analysis API

This week, we launched five challenges as part of the Ethereal Virtual Hackathon with a prize pool of $6k (paid in crypto, obviously). This quick guide explains how to perform an analysis with MythX API.

What is MythX?

MythX is a security analysis platform for Ethereum smart contracts. It performs a comprehensive range of industry-leading analyses on smart contracts, including input fuzzing, static and symbolic analysis.

The goal of MythX is to make security analysis available to all Ethereum developers — even those who are not security-savvy. In the ongoing Hackathon we award prizes in five categories. For more details on the requirements and prizes check out the Gitcoin issues:

How MythX API works

MythX clients submit Solidity code and solc compiler artifacts to the MythX API (https://api.mythx.io) for analysis. The required imput data can be generated by compiling source code with solc or solc-js. Prerequisite for analysis is that the code is free of syntax errors and compiles successfully. On submitting the request, the analysis service returns an UUID which can then be used to query the analysis status and obtain the results.

The MythX OpenAPI specification describes the API request and response format in detail. However, the easiest way to get familiar with the API is by trying it yourself.

Analysis Walkthrough

In the following walkthrough we’ll use PythX, a Python library that also comes with a simple command line interface (if you’re a JavaScript fan and/or Python hater, you can get similar results by running Sabre with the--debug flag). The first step is to install PythX:

$ pip3 install pythx

You can show the available commands by running pythx --help.

$ pythx --help
Usage: pythx [OPTIONS] COMMAND [ARGS]...
PythX is a CLI/library for the MythX smart contract security analysis API.
Options:  --help  Show this message and exit.
Commands:  check    Submit a new analysis job based on source code, byte code, or...  login    Login to your MythX account  logout   Log out of your MythX account  openapi  Get the OpenAPI spec in HTML or YAML format  ps       Get a greppable overview of submitted analyses  refresh  Refresh your MythX API token  report   Check the detected issues of a finished analysis job  status   Get the status of an analysis by its UUID  top      Display the most recent analysis jobs and their status  truffle  Submit a Truffle project to MythX  version  Print version information of PythX and the API

Note that Pythx’s commands closely mirror the API specification: There’s separate commands for login, refresh, submitting an analysis, and so on. Setting the PYTHX_DEBUG environment variable enables verbose debugging output. We’ll use this to get a closer look at the low-level API requests.

$ export PYTHX_DEBUG=1

Authentication

MythX API uses username/password authentication based on JSON Web Tokens (JWT). Users are identified by their Ethereum address and a password chosen when signing up.

To get started as a MythX developer I recommend signing up for a free account on the MythX website. During the beta, which will run at least until the start of June, free accounts are unrestricted, and we’ll provide special accounts to tool devs once paid subscriptions become available.

To accommodate users who want to try out MythX tools prior to signing up, there is also a built-in trial account with limited capabilities. Specifically, the trial user only receives up to three security issues detected per analysis and cannot list or access historical analyses. The credentials for the trial user are:

Username: 0x0000000000000000000000000000000000000000Password: trial

To view the login request, type:

$ pythx login

This will prompt you for an Ethereum address and password. PythX will then send a POST request to the /auth/login endpoint:

POST https://api.mythx.io/v1/auth/login HTTP/1.1Content-Length: 90Content-Type: application/json
{"ethAddress": "0x[...]", "password": "[password]"}

If the credentials are valid, the server sends a JSON-formatted response containing the JWT access token and refresh token. By submitting the access token in the Bearer header you can use authenticated endpoints. The access token is valid for 10 minutes, after which you can obtain a new one using the refresh token.

Running an Analysis

While MythX can run an analysis on EVM bytecode only, you have to submit both the source code and bytecode to receive a complete result. The following options exist:

  1. Submit bytecode only. In this case, you need to submit both the creation bytecode and runtime bytecode in thebytecode and deployedBytecode fields, respectively. Note that in this case, you will only receive partial results and the false positive rate will be higher.
  2. Submit bytecode and Solidity code. Here, you submit the creation and runtime bytecode as well as the source mappings generated by solc. Additionally, you submit a the list of input filenames in the sourceList field and the source code for each file in the sources field. Note that you must include the filenames and code for all imports (and recursively for imports of imports) as well. Finally, when submitting source code, you must add a mainSource field that tells MythX about the primary file being analyzed.
  3. Submit bytecode and ASTs. Same as above, but you submit the abstract syntax tree (AST) of each file instead of the source code. Assuming you are using solc, this is easier to implement than option 2 because solc provides the ASTs for all imports automatically — you can simply pass on the output of solc instead of manually adding the source code for each import. Also, the mainSource field can be ommitted when using ASTs.

As an example, let’s look at the first challenge of the MythX workshop. To perform an analysis from Solidity source with PythX, make sure you that solc is installed an in the path, then run:

$ pythx check -sf Token.sol

What PythX does is running the solc command line tool with the following arguments:

solc --combined-json ast,bin,bin-runtime,srcmap,srcmap-runtime <file>

It then formats the API request according to specification and sends a POST request to the analysis endpoint. The submitted JSON object looks as follows (truncated for brevity):

POST https://api.mythx.io/v1/analysesAuthorization: Bearer [Access token]Content-Length: 18124Content-Type: application/json
{  "data": {    "bytecode": "[token.sol creation bytecode]",    "sourceMap": "25:503:0:...",    "deployedBytecode": "[token.sol bytecode]",    "deployedSourceMap": "25:503:0:...",    "mainSource": "token.sol",    "sources": {      "token.sol": {        "ast": {},        "source": "[Soldity code for token.sol]"      }    },    "sourceList": [      "token.sol"    ],    "version": "0.5.7+commit.6da8b019.Linux.g++",    "analysisMode": "quick"  },  "clientToolName": "pythx"}

Note the two additional configuration parameters:

  • analysisMode: Currently, there are two analysis modes that differ in the execution time available to the fuzzer and symbolic analyzer. The “quick” mode takes 45–90 seconds to complete, while the “full” mode takes 5–10 minutes. Full mode allows for a deeper analysis that can discover more bugs, such as bugs that require multiple transactions to execute. We are currently working on a third mode (codename “lighting”) that returns a result within a few seconds.
  • clientToolName: This field allows you to pick an arbitrary name for your tool. We track usage of different MythX tools for the purpose of revenue sharing: After paid subscriptions go live, 25% of revenues will be split between tool devs proportional to the number of active of active paying users of each tool.

In the response to a newly submitted analysis you will receive a job UUID (allowing you to track analysis progress), as well as some useful meta data. This includes our backend tool versions, a timestamp, the user’s ID, as well as the time the job has been queued and is running. With the status field you are able to track whether your analysis has finished.

{  "apiVersion": "v1.4.14",  "harveyVersion": "0.0.18",  "maestroVersion": "1.2.10",  "maruVersion": "0.4.4",  "mythrilVersion": "0.20.4",  "queueTime": 1488,  "runTime": 11572,  "status": "Queued",  "submittedAt": "2019-04-20T09:22:56.522Z",  "submittedBy": "5c6d656206d17300110e24d6",  "uuid": "d257381b-97b0-4fce-9832-7da2f8ca2ebb"}

Note that initially, the analysis status is shown as “queued”. Each analysis request goes through three phases:

  • Queued: The job has been accepted but not yet picked up by a worker. As long as the API is not overloaded, jobs should remain in “queued” state for only a few seconds.
  • In progress: The analysis is currently running. In “quick” mode, the analysis should take 45–90 seconds to complete.
  • Finished: The analysis is completed and the report can be obtained.

PythX displays these objects in a nicer way through its CLI:

$ pythx status d257381b-97b0-4fce-9832-7da2f8ca2ebb╒════════════════╤══════════════════════════════════════╕│ uuid           │ d257381b-97b0-4fce-9832-7da2f8ca2ebb │├────────────────┼──────────────────────────────────────┤│ apiVersion     │ v1.4.14                              │├────────────────┼──────────────────────────────────────┤│ mythrilVersion │ 0.20.4                               │├────────────────┼──────────────────────────────────────┤│ maestroVersion │ 1.2.10                               │├────────────────┼──────────────────────────────────────┤│ harveyVersion  │ 0.0.18                               │├────────────────┼──────────────────────────────────────┤│ maruVersion    │ 0.4.4                                │├────────────────┼──────────────────────────────────────┤│ queueTime      │ 1488                                 │├────────────────┼──────────────────────────────────────┤│ runTime        │ 11572                                │├────────────────┼──────────────────────────────────────┤│ status         │ In Progress                          │├────────────────┼──────────────────────────────────────┤│ submittedAt    │ 2019-04-20T09:22:56.522Z             │├────────────────┼──────────────────────────────────────┤│ submittedBy    │ 5c6d656206d17300110e24d6             │╘════════════════╧══════════════════════════════════════╛

Once your job is done, you will see the following entry in the status object:

"status":"Finished"

Retrieving Results

Once the job is in “finished” state we can retrieve the results with the pythx report command.

$ pythx report d257381b-97b0–4fce-9832–7da2f8ca2ebb

This sends an authenticated request to the /analysis/UUID/report endpoint:

GET https://api.mythx.io/v1/analyses/d257381b-97b0–4fce-9832–7da2f8ca2ebb/issues HTTP/1.1 200Authorization: Bearer [Access token]

A list of detected security issues is returned in the response.

HTTP/1.1 200Content-Type: application/json; charset=utf-8
[  {    "issues": [      {        "swcID": "SWC-101",        "swcTitle": "Integer Overflow and Underflow",        "description": {          "head": "The binary subtraction can underflow.",          "tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion."        },        "severity": "High",        "locations": [          {            "sourceMap": "296:29:1"          }        ],        "extra": {          "testCase": {            "initialState": {              "accounts": null            },            "steps": null          }        }      },      {        "swcID": "SWC-101",        "swcTitle": "Integer Overflow and Underflow",        "description": {          "head": "The binary subtraction can underflow.",          "tail": "The operands of the subtraction operation are not sufficiently constrained. The subtraction could therefore result in an integer underflow. Prevent the underflow by checking inputs or ensure sure that the underflow is caught by an assertion."        },        "severity": "High",        "locations": [          {            "sourceMap": "337:30:1"          }        ],        "extra": {          "testCase": {            "initialState": {              "accounts": null            },            "steps": null          }        }      },      {        "swcID": "SWC-101",        "swcTitle": "Integer Overflow and Underflow",        "description": {          "head": "The binary addition can overflow.",          "tail": "The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion."        },        "severity": "High",        "locations": [          {            "sourceMap": "373:23:1"          }        ],        "extra": {          "testCase": {            "initialState": {              "accounts": null            },            "steps": null          }        }      }    ],    "sourceType": "solidity-file",    "sourceFormat": "text",    "sourceList": [      "token.sol"    ],    "meta": {      "coveredInstructions": 318,      "coveredPaths": 9    }  }]

PythX, just like other tools in the MythX ecosystem, resolves the given source locations and maps them to line numbers in the Solidity input files. The result from a CLI call getting the report will be displayed as a prettier table:

Client Libraries and Tools

The MythX API is just the first step for us. We aim to build an open-source ecosystem that allows developers of varying skill levels to easily build tools specific to their needs. Security is an integral part of building a sustainable ecosystem. We practice what we preach, so we already came up with a nice little set of tools and libraries that you can get inspiration from. :)

Getting Support

Processing build artifacts and source mappings correctly can become tricky for complex Soldity projects. On way to make things easier is to re-use code of the existing projects listed above. You can also get in contact with the team and other tool devs on the Discord server.

Further links

A Deep Dive into the MythX Smart Contract Security Analysis API was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.

Publication date: 
04/22/2019 - 00:30