{"id":15065111,"url":"https://github.com/decurity/semgrep-smart-contracts","last_synced_at":"2025-04-07T05:06:55.461Z","repository":{"id":41460842,"uuid":"476727342","full_name":"Decurity/semgrep-smart-contracts","owner":"Decurity","description":"Semgrep rules for smart contracts based on DeFi exploits","archived":false,"fork":false,"pushed_at":"2024-09-06T19:03:07.000Z","size":476,"stargazers_count":653,"open_issues_count":12,"forks_count":89,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-04-07T05:06:05.295Z","etag":null,"topics":["defi","ethereum","security","semgrep","solidity"],"latest_commit_sha":null,"homepage":"","language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Decurity.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-01T13:15:39.000Z","updated_at":"2025-04-02T11:23:08.000Z","dependencies_parsed_at":"2023-02-19T05:01:34.590Z","dependency_job_id":"971759d1-28f4-47ee-8cdb-846d7c200410","html_url":"https://github.com/Decurity/semgrep-smart-contracts","commit_stats":null,"previous_names":["raz0r/semgrep-smart-contracts"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Decurity%2Fsemgrep-smart-contracts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Decurity%2Fsemgrep-smart-contracts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Decurity%2Fsemgrep-smart-contracts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Decurity%2Fsemgrep-smart-contracts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Decurity","download_url":"https://codeload.github.com/Decurity/semgrep-smart-contracts/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247595334,"owners_count":20963943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["defi","ethereum","security","semgrep","solidity"],"created_at":"2024-09-25T00:34:21.818Z","updated_at":"2025-04-07T05:06:55.427Z","avatar_url":"https://github.com/Decurity.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Semgrep rules for smart contracts\n\nIn 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).\n\n## Disclaimer\n\nCurrently 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.\n\n## Scanning\n\n\u003e **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.\n\n1) By cloning the repository:\n\n  ```shell\n  $ semgrep --config solidity/security path/to/your/project\n  ```\n\n2) By using [semgrep registry](https://semgrep.dev/r):\n\n  ```shell\n  $ semgrep --config p/smart-contracts path/to/your/project\n  ```\n\n3) In your CI:\n\nCreate `run-semgrep.yaml` in `.github/workflows` with the following contents:\n\u003cdetails\u003e\n  \u003csummary\u003erun-semgrep.yaml\u003c/summary\u003e\n  \n```yaml\n# Name of this GitHub Actions workflow.\nname: Run Semgrep\n\non:\n  # Scan changed files in PRs (diff-aware scanning):\n  pull_request: {}\n  # On-demand \n  workflow_dispatch: {}\n\njobs:\n  semgrep:\n    # User-definable name of this GitHub Actions job:\n    name: Scan\n    # If you are self-hosting, change the following `runs-on` value: \n    runs-on: ubuntu-latest\n\n    container:\n      # A Docker image with Semgrep installed. Do not change this.\n      image: returntocorp/semgrep\n\n    # Skip any PR created by dependabot to avoid permission issues:\n    if: (github.actor != 'dependabot[bot]')\n\n    steps:\n      # Fetch project source with GitHub Actions Checkout.\n      - uses: actions/checkout@v3\n      # Fetch semgrep rules\n      - name: Fetch semgrep rules\n        uses: actions/checkout@v3\n        with:\n          repository: decurity/semgrep-smart-contracts\n          path: rules\n      # Run security and gas optimization rules\n      - run: semgrep ci --sarif --output=semgrep.sarif || true\n        env:\n           SEMGREP_RULES: rules/solidity/security rules/solidity/performance\n      # Upload findings to GitHub Advanced Security Dashboard\n      - name: Upload findings to GitHub Advanced Security Dashboard\n        uses: github/codeql-action/upload-sarif@v2\n        with:\n          sarif_file: semgrep.sarif\n        if: always()\n```\n\u003c/details\u003e\n\n## Testing\n\nEach rule is accompanied by an actual vulnerable source code that was targeted by an exploit. Vulnerable lines are marked with `// ruleid: ...`\n\nIn case a rule is not yet supported by semgrep, you will find `// todoruleid: ...`\n\nRun tests: \n\n```shell\n$ semgrep --test solidity\n```\n\nValidate rules: \n\n```shell\n$ semgrep --validate --config solidity\n```\n\nFeel free to submit any issues with the precision and quality of the rules!\n\n## Security Rules\n\nRule ID | Targets | Description\n--- | --- | ---\ncompound-borrowfresh-reentrancy | Compound, Ola Finance, Hundred Finance, Agave | Function borrowFresh() in Compound performs state update after doTransferOut()\ncompound-sweeptoken-not-restricted | TUSD, Compound | Function sweepToken is allowed to be called by anyone\nerc20-public-transfer | Creat Future | Custom ERC20 implementation exposes _transfer() as public\nerc20-public-burn | HospoWise | Anyone can burn tokens of other accounts\nerc677-reentrancy | Ola Finance | ERC677 callAfterTransfer() reentrancy\nerc777-reentrancy | Bacon Protocol | ERC777 tokensReceived() reentrancy\nerc721-reentrancy | Hype Bears | ERC721 onERC721Received() reentrancy\nerc721-arbitrary-transferfrom | Distortion Genesis | Custom ERC721 implementation lacks access control checks in _transfer()\ngearbox-tokens-path-confusion | Gearbox | UniswapV3 adapter implemented incorrect extraction of path parameters\nkeeper-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.\nbasic-oracle-manipulation | Onering Finance, Deus Finance | getSharePrice() can be manipulated via flashloan\nredacted-cartel-custom-approval-bug | Redacted Cartel | transferFrom() can steal allowance of other accounts\nrigoblock-missing-access-control | RigoBlock | setMultipleAllowances() is missing onlyOwner modifier\noracle-price-update-not-restricted | Rikkei Finance, Aave | Oracle price data can be submitted by anyone\nsuperfluid-ctx-injection | Superfluid | A specially crafted calldata may be used to impersonate other accounts\ntecra-coin-burnfrom-bug | Tecra Coin | Parameter \"from\" is checked at incorrect position in \"_allowances\" mapping\narbitrary-low-level-call | Auctus Options, Starstream Finance, BasketDAO, Li Finance | An attacker may perform call() to an arbitrary address with controlled calldata\nsense-missing-oracle-access-control | Sense Finance | Oracle update is not restricted in onSwap(), rule by [Arbaz Kiraak](https://twitter.com/ArbazKiraak)\nproxy-storage-collision | Audius | Proxy declares a state var that may override a storage slot of the implementation\nuniswap-callback-not-protected | Generic | Uniswap callback is not protected\nencode-packed-collision | Generic | Hash collision with variable length arguments in abi.encodePacked\nopenzeppelin-ecdsa-recover-malleable | OpenZeppelin | Potential signature malleability\nBETA: basic-arithmetic-underflow | Umbrella Network, Remittance Token | Possible arithmetic underflow\nunrestricted-transferownership | Ragnarok Online Invasion | Contract ownership can be transfered by anyone\nmsg-value-multicall | Sushiswap | Function with constant msg.value can be called multiple times\nno-bidi-characters | Generic | The code must not contain any of Unicode Direction Control Characters\ndelegatecall-to-arbitrary-address | Generic | An attacker may perform delegatecall() to an arbitrary address.\nincorrect-use-of-blockhash | Generic | blockhash(block.number) and blockhash(block.number + N) always returns 0.\naccessible-selfdestruct | Generic | Contract can be destructed by anyone in $FUNC\nno-slippage-check| Generic|  No slippage check in a Uniswap v2/v3 trade\nbalancer-readonly-reentrancy-getrate | Balancer | getRate() call on a Balancer pool is not protected from the read-only reentrancy.\nbalancer-readonly-reentrancy-getpooltokens | Balancer | getPoolTokens() call on a Balancer pool is not protected from the read-only reentrancy.\ncurve-readonly-reentrancy | Curve | get_virtual_price() call on a Curve pool is not protected from the read-only reentrancy.\npublic-transfer-fees-supporting-tax-tokens | LeetSwap | public _transferFeesSupportingTaxTokens() without any modificators \nolympus-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\ncompound-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()\nthirdweb-vulnerability | Swopple Token, TIME Token, NAME Token, HXA Token | In contracts that support Multicall and ERC2771Context an Arbitrary Address Spoofing attack is possible\nexact-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.\nmissing-assignment | Generic | Meaningless statement that does not change any values could be a sign of missed security checks or other important changes.\noracle-uses-curve-spot-price | UwU | Oracle uses the get_p() Curve pool function which can be manipulated via flashloan to calculate the asset price\nbad-transferfrom-access-control | Generic | Funds approved by users can be stolen because of improper access control to a transferFrom function \n\n## Gas Optimization Rules\n\nRule ID | Description\n--- | ---\narray-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.\ninit-variables-with-default-value | Explicitly initializing a variable with its default value costs unnecessary gas.\nstate-variable-read-in-a-loop | Replace state variable reads and writes within loops with local variable reads and writes.\nunnecessary-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.\nuse-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.\nuse-multiple-require | Using multiple require statements is cheaper than using \u0026\u0026 multiple check combinations. \nuse-nested-if | Using nested is cheaper than using \u0026\u0026 multiple check combinations.\nuse-prefix-decrement-not-postfix | The prefix decrement expression is cheaper in terms of gas.\nuse-prefix-increment-not-postfix | The prefix increment expression is cheaper in terms of gas.\nuse-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.\nnon-payable-constructor | Consider making costructor payable to save gas.\nnon-optimal-variables-swap | Consider swapping variables using `($VAR1, $VAR2) = ($VAR2, $VAR1)` to save gas.\ninefficient-state-variable-increment | \u003cx\u003e += \u003cy\u003e costs more gas than \u003cx\u003e = \u003cx\u003e + \u003cy\u003e for state variables.\n\n## Best Practices Rules\n\nRule ID | Description\n--- | ---\nuse-abi-encodecall-instead-of-encodewithselector | To guarantee arguments type safety it is recommended to use `abi.encodeCall` instead of `abi.encodeWithSelector`.\nuse-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.\n\n## Solana Rules\nRule ID | Description\n--- | ---\nsolana-arbitrary-program-call | An attacker may be able to invoke arbitrary programs without address validations\nsolana-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\n\n## Cairo Rules\nRule ID | Description\n--- | ---\nlack-of-error-message  | Error message is missing in the assert statement\ntx-origin-authentication | Using `account_contract_address` for authentication is insecure. Use `get_caller_address` or an appropriate method for verifying users.\nview-fn-mutable-state | View function should not be able to modify state\nview-fn-writes | View function should not write to the state\nzero-division | Possible division by zero","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecurity%2Fsemgrep-smart-contracts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdecurity%2Fsemgrep-smart-contracts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecurity%2Fsemgrep-smart-contracts/lists"}