How to Audit Solana Smart Contracts Part 2: Automated Scanning

November 12, 2021

Following Part 1: a systematic approach, this article introduces a few automated scanning tools to help audit Solana smart contracts.

  • Soteria: dedicated scanner for Solana programs that finds all the common security vulnerabilities (e.g., missing checks, arithmetic overflows, etc).
  • cargo-audit: audit Cargo.lock files for known security vulnerabilities
  • cargo-clippy: a collection of lints to catch common mistakes.
  • cargo-geiger: reports usage of unsafe Rust.
  • cargo-spellcheck: checks for spelling and grammar mistakes

We next use two real contracts (solido and jet-v1) to showcase the capabilities of these tools. Both solido and jet-v1 offer bug bounties on Immunefi.

Soteria: scanning all the common vulnerabilities

Soteria is an auto-scanner developed by the Stoeria team dedicated for finding all the common vulnerabilities in Solana smart contracts.

  • To install soteria , run the following command in a Linux terminal:
$ sh -c "$(curl -k https://supercompiler.xyz/install)"
  • To run soteria, invoke `soteria .` or `soteria -analyzeAll .` under the smart contract’s directory (where Xargo.tomlexists)

We next use two examples to showcase Soteria.

Example 1: a missing check in solido

In this pull request, solido applied a fix to a missing check on the reserve_account(line 151 below):

This missing checking is a critical security vulnerability. It allows an attacker to mint and receive unlimited token by supplying an attacker-controlled reserve_account.

To reproduce this vulnerability, we checked out the newest version of solido from github:

$ git clone git@github.com:ChorusOne/solido.git

and commented out the line containing the check (in file solido/program/src/processor.rs):

lido.check_reserve_account(program_id, accounts.lido.key, accounts.reserve_account)?;

By running soteria -analyzeAll ., Soteria only takes a few seconds to detect this vulnerability and will also report the following in the terminal:

Figure 1. a missing check vulnerability in solido reported by Soteria

Example 2: an integer overflow in jet-v1

In this commit, jet-v1 applied a fix to an Integer overflow in the borrow function (line 119 below):

The possible consequences of this overflow are:

  1. A large amount will be subtracted from the total_deposits in reserve, although only a small amount is eventually loaned to the borrower.
  2. After a successful loan transaction, a borrower who requests a large amount may actually receive a small amount loan.

To reproduce this vulnerability, we checked out the newest version of jet-v1 from github:

$ git clone https://github.com/jet-lab/jet-v1

and changed the check_add fix (line 122 in file programs/jet/src/instructions/borrow.rs):

let total_token_debt = requested_tokens.checked_add(fees)
  .expect("Requested a debt that would exceed the maximum potential supply for a token.");

back to:

let total_token_debt = requested_tokens + fees;

Again, by running soteria -analyzeAll ., Soteria detects this vulnerability in a few seconds and reports the following in the terminal:

Figure 2. an integer overflow vulnerability in jet-v1 reported by Soteria

cargo-audit: scanning Cargo.lock for vulnerabilities

cargo-audit is a tool to audit `Cargo.lock` files for crates with security vulnerabilities reported to the RustSec Advisory Database.

To install, execute `cargo install cargo-audit`

To run, execute cargo audit at the top level of any Cargo project (where Cargo.lock exists).

The following shows the result of cargo audit on solido. It loaded 371 security advisories and scanned 143 crate dependencies, but did not find vulnerabilities.

Fetching advisory database from `https://github.com/RustSec/advisory-db.git`
Loaded 371 security advisories (from /root/.cargo/advisory-db)
Updating crates.io index
Scanning Cargo.lock for vulnerabilities (143 crate dependencies)

cargo-clippy: lints to catch common mistakes

cargo-clippy is a linter to catch common mistakes in Rust code. It has a collection of over 450 lint rules.

To install, execute rustup update and rustup component add clippy

To run, execute cargo clippy under the smart contract’s directory (where Xargo.toml exists).

cargo clippy reports a large number of warnings on jet-v1. The following shows a few of them:

warning: length comparison to zero
--> libraries/math/src/number.rs:188:34
188 |         let pretty_decimals = if stripped_decimals.len() == 0 {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
= help: using `is_empty` is clearer and more explicit: 
    `stripped_decimals.is_empty()` 
= note: `#[warn(clippy::len_zero)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#len_zero


warning: the function `handler` doesn't need a mutable reference
--> programs/jet/src/instructions/liquidate_dex.rs:594:45
594 |     handler(&source_market, &target_market, &mut liquidation)?;
    |                                             ^^^^^^^^^^^^^^^^
= note: `#[warn(clippy::unnecessary_mut_passed)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed

cargo-geiger: scanning usages of unsafe Rust

cargo-geiger is a tool that detects the usage of unsafe Rust code. It lists statistics in a Rust crate and all its dependencies.

To install, execute cargo install cargo-geiger

To run, execute cargo geiger under the smart contract’s directory.

The following is a screenshot of the statistics on jet-v1 reported by cargo geiger:

cargo-spellcheck: spelling and grammar mistakes

cargo-spellcheck is a tool that checks for spelling and grammar mistakes in Rust code and documentation. It may not appear useful to find security-related issues, but can be helpful to pinpoint typos in many cases.

To install, execute cargo install --locked cargo-spellcheck

To run, execute cargo spellcheck under the smart contract’s directory.

The following shows a few warnings reported by cargo spellcheck on jet-v1:

error: spellcheck(Hunspell)
--> jet-v1/programs/jet/src/state/market.rs:357
    |
357 |  Disable all borrowing and collateral withdrawls
    |                                       ^^^^^^^^^^ 
- withdraws, withdrawals, with drawls, with-drawls, withdraw ls, withdraw-ls, withdrawal, or one of 2 others

--> jet-v1/programs/jet/src/state/reserve.rs:104
104 |  liquidating assetr from this reserve as collateral.
    |              ^^^^^^
    | - assert, asset, assets, or asset r

Soteria audit

The Soteria team is pleased to provide audit services to high-impact Dapps on Solana. Email contact@soteria.dev or visit soteria.dev

Soteria is founded by leading minds in the fields of blockchain security and software verification.

What’s next

In the next few articles, we will continue to introduce auditing skills for Solana smart contracts, including automated testing tools and Anchor.

How to audit Solana smart contracts series?

For all blogs by Soteria, Please visit https://soteria.dev/blogs