Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/decurity/semgrep-smart-contracts

Semgrep rules for smart contracts based on DeFi exploits
https://github.com/decurity/semgrep-smart-contracts

defi ethereum security semgrep solidity

Last synced: 2 days ago
JSON representation

Semgrep rules for smart contracts based on DeFi exploits

Awesome Lists containing this project

README

        

# Semgrep rules for smart contracts

In this repository you can find [semgrep](https://semgrep.dev/) rules that look for patterns of vulnerabilities in smart contracts based on actual DeFi exploits as well as gas optimization rules that can be used as a part of the CI pipeline. The rules are part of the semgrep registry under [p/smart-contracts](https://semgrep.dev/p/smart-contracts).

## Disclaimer

Currently semgrep supports [Solidity](https://semgrep.dev/docs/language-support/) in `experimental` mode. Some of the rules may not work until Solidity is in `beta` at least.

## Scanning

> **Important:** Some of the rules utilize the [taint mode](https://semgrep.dev/docs/writing-rules/data-flow/taint-mode), which is restricted to the same function in the open-source version of semgrep. To take advantage of intra-procedural taint analysis, you must include the `--pro` flag with each command. Please note that this requires semgrep Pro.

1) By cloning the repository:

```shell
$ semgrep --config solidity/security path/to/your/project
```

2) By using [semgrep registry](https://semgrep.dev/r):

```shell
$ semgrep --config p/smart-contracts path/to/your/project
```

3) In your CI:

Create `run-semgrep.yaml` in `.github/workflows` with the following contents:

run-semgrep.yaml

```yaml
# Name of this GitHub Actions workflow.
name: Run Semgrep

on:
# Scan changed files in PRs (diff-aware scanning):
pull_request: {}
# On-demand
workflow_dispatch: {}

jobs:
semgrep:
# User-definable name of this GitHub Actions job:
name: Scan
# If you are self-hosting, change the following `runs-on` value:
runs-on: ubuntu-latest

container:
# A Docker image with Semgrep installed. Do not change this.
image: returntocorp/semgrep

# Skip any PR created by dependabot to avoid permission issues:
if: (github.actor != 'dependabot[bot]')

steps:
# Fetch project source with GitHub Actions Checkout.
- uses: actions/checkout@v3
# Fetch semgrep rules
- name: Fetch semgrep rules
uses: actions/checkout@v3
with:
repository: decurity/semgrep-smart-contracts
path: rules
# Run security and gas optimization rules
- run: semgrep ci --sarif --output=semgrep.sarif || true
env:
SEMGREP_RULES: rules/solidity/security rules/solidity/performance
# Upload findings to GitHub Advanced Security Dashboard
- name: Upload findings to GitHub Advanced Security Dashboard
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: semgrep.sarif
if: always()
```

## Testing

Each rule is accompanied by an actual vulnerable source code that was targeted by an exploit. Vulnerable lines are marked with `// ruleid: ...`

In case a rule is not yet supported by semgrep, you will find `// todoruleid: ...`

Run tests:

```shell
$ semgrep --test solidity
```

Validate rules:

```shell
$ semgrep --validate --config solidity
```

Feel free to submit any issues with the precision and quality of the rules!

## Security Rules

Rule ID | Targets | Description
--- | --- | ---
compound-borrowfresh-reentrancy | Compound, Ola Finance, Hundred Finance, Agave | Function borrowFresh() in Compound performs state update after doTransferOut()
compound-sweeptoken-not-restricted | TUSD, Compound | Function sweepToken is allowed to be called by anyone
erc20-public-transfer | Creat Future | Custom ERC20 implementation exposes _transfer() as public
erc20-public-burn | HospoWise | Anyone can burn tokens of other accounts
erc677-reentrancy | Ola Finance | ERC677 callAfterTransfer() reentrancy
erc777-reentrancy | Bacon Protocol | ERC777 tokensReceived() reentrancy
erc721-reentrancy | Hype Bears | ERC721 onERC721Received() reentrancy
erc721-arbitrary-transferfrom | Distortion Genesis | Custom ERC721 implementation lacks access control checks in _transfer()
gearbox-tokens-path-confusion | Gearbox | UniswapV3 adapter implemented incorrect extraction of path parameters
keeper-network-oracle-manipulation | Inverse Finance | Keep3rV2.current() call has high data freshness, but it has low security, an exploiter simply needs to manipulate 2 data points to be able to impact the feed.
basic-oracle-manipulation | Onering Finance, Deus Finance | getSharePrice() can be manipulated via flashloan
redacted-cartel-custom-approval-bug | Redacted Cartel | transferFrom() can steal allowance of other accounts
rigoblock-missing-access-control | RigoBlock | setMultipleAllowances() is missing onlyOwner modifier
oracle-price-update-not-restricted | Rikkei Finance, Aave | Oracle price data can be submitted by anyone
superfluid-ctx-injection | Superfluid | A specially crafted calldata may be used to impersonate other accounts
tecra-coin-burnfrom-bug | Tecra Coin | Parameter "from" is checked at incorrect position in "_allowances" mapping
arbitrary-low-level-call | Auctus Options, Starstream Finance, BasketDAO, Li Finance | An attacker may perform call() to an arbitrary address with controlled calldata
sense-missing-oracle-access-control | Sense Finance | Oracle update is not restricted in onSwap(), rule by [Arbaz Kiraak](https://twitter.com/ArbazKiraak)
proxy-storage-collision | Audius | Proxy declares a state var that may override a storage slot of the implementation
uniswap-callback-not-protected | Generic | Uniswap callback is not protected
encode-packed-collision | Generic | Hash collision with variable length arguments in abi.encodePacked
openzeppelin-ecdsa-recover-malleable | OpenZeppelin | Potential signature malleability
BETA: basic-arithmetic-underflow | Umbrella Network, Remittance Token | Possible arithmetic underflow
unrestricted-transferownership | Ragnarok Online Invasion | Contract ownership can be transfered by anyone
msg-value-multicall | Sushiswap | Function with constant msg.value can be called multiple times
no-bidi-characters | Generic | The code must not contain any of Unicode Direction Control Characters
delegatecall-to-arbitrary-address | Generic | An attacker may perform delegatecall() to an arbitrary address.
incorrect-use-of-blockhash | Generic | blockhash(block.number) and blockhash(block.number + N) always returns 0.
accessible-selfdestruct | Generic | Contract can be destructed by anyone in $FUNC
no-slippage-check| Generic| No slippage check in a Uniswap v2/v3 trade
balancer-readonly-reentrancy-getrate | Balancer | getRate() call on a Balancer pool is not protected from the read-only reentrancy.
balancer-readonly-reentrancy-getpooltokens | Balancer | getPoolTokens() call on a Balancer pool is not protected from the read-only reentrancy.
curve-readonly-reentrancy | Curve | get_virtual_price() call on a Curve pool is not protected from the read-only reentrancy.
public-transfer-fees-supporting-tax-tokens | LeetSwap | public _transferFeesSupportingTaxTokens() without any modificators
olympus-dao-staking-incorrect-call-order | OlympusDAO, FloorDAO, Heavens Gate, Jump Farm, QuantumWN | The order of calling the transferFrom() and rebase() functions is incorrect in Olympus DAO forks
compound-precision-loss | Hundred Finance, Midas Finance, Onyx Protocol | In Compound forks if there is a market with totalSupply = 0 and collateralFactor != 0 a precision loss attack is possible if redeemAmount is taken from the arguments of redeemFresh()
thirdweb-vulnerability | Swopple Token, TIME Token, NAME Token, HXA Token | In contracts that support Multicall and ERC2771Context an Arbitrary Address Spoofing attack is possible
exact-balance-check | Generic | Testing the balance of an account as a basis for some action has risks associated with unexpected receipt of ether or another token, including tokens deliberately transfered to cause such tests to fail, as an MEV attack.
missing-assignment | Generic | Meaningless statement that does not change any values could be a sign of missed security checks or other important changes.
oracle-uses-curve-spot-price | UwU | Oracle uses the get_p() Curve pool function which can be manipulated via flashloan to calculate the asset price
bad-transferfrom-access-control | Generic | Funds approved by users can be stolen because of improper access control to a transferFrom function

## Gas Optimization Rules

Rule ID | Description
--- | ---
array-length-outside-loop | Caching the array length outside a loop saves reading it on each iteration, as long as the array's length is not changed during the loop.
init-variables-with-default-value | Explicitly initializing a variable with its default value costs unnecessary gas.
state-variable-read-in-a-loop | Replace state variable reads and writes within loops with local variable reads and writes.
unnecessary-checked-arithmetic-in-loop | A lot of times there is no risk that the loop counter can overflow. Using Solidity's unchecked block saves the overflow checks.
use-custom-error-not-require | Consider using custom errors as they are more gas efficient while allowing developers to describe the error in detail using NatSpec.
use-multiple-require | Using multiple require statements is cheaper than using && multiple check combinations.
use-nested-if | Using nested is cheaper than using && multiple check combinations.
use-prefix-decrement-not-postfix | The prefix decrement expression is cheaper in terms of gas.
use-prefix-increment-not-postfix | The prefix increment expression is cheaper in terms of gas.
use-short-revert-string | Shortening revert strings to fit in 32 bytes will decrease gas costs for deployment and gas costs when the revert condition has been met.
non-payable-constructor | Consider making costructor payable to save gas.
non-optimal-variables-swap | Consider swapping variables using `($VAR1, $VAR2) = ($VAR2, $VAR1)` to save gas.
inefficient-state-variable-increment | += costs more gas than = + for state variables.

## Best Practices Rules

Rule ID | Description
--- | ---
use-abi-encodecall-instead-of-encodewithselector | To guarantee arguments type safety it is recommended to use `abi.encodeCall` instead of `abi.encodeWithSelector`.
use-ownable2step | By demanding that the receiver of the owner permissions actively accept via a contract call of its own, `Ownable2Step` and `Ownable2StepUpgradeable` prevent the contract ownership from accidentally being transferred to an address that cannot handle it.

## Solana Rules
Rule ID | Description
--- | ---
solana-arbitrary-program-call | An attacker may be able to invoke arbitrary programs without address validations
solana-insecure-account-closing | Writing the CLOSED_ACCOUNT_DISCRIMINATOR to a closed account is crucial to prevent the reuse of the account within the same transaction

## Cairo Rules
Rule ID | Description
--- | ---
lack-of-error-message | Error message is missing in the assert statement
tx-origin-authentication | Using `account_contract_address` for authentication is insecure. Use `get_caller_address` or an appropriate method for verifying users.
view-fn-mutable-state | View function should not be able to modify state
view-fn-writes | View function should not write to the state
zero-division | Possible division by zero