Code Inspector

Code Inspector seamlessly integrates with Github to maximize security with every step of your development process via automatic code analysis powered by machine learning intelligence and state-of-the-art tools developed by our security experts.

For every push to your code, the OpenZeppelin Code Inspector dives into a detailed examination, identifying potential vulnerabilities and suggesting improvements to enhance your code quality. It generates a succinct report, summarizable in your PR comments for quick and immediate access, while a more detailed report is made available on Defender.

Use cases

  • Automatically conduct security analysis on pull requests, identifying vulnerabilities and suggesting improvements.

  • Utilize summarized reports in the pull request for immediate insights into your code’s health and security.

  • Access comprehensive, detailed reports on Defender for an in-depth understanding of potential vulnerabilities and code optimization areas.

  • Use OpenZeppelin’s Dependency Checker to identify reused contracts and match them against a database of known vulnerabilities.

  • Apply static analysis rules to Solidity files, identifying potential issues and their severity for high-quality code maintenance.

Features

Some issues found by Code Inspector are detected by our AI models. Keep in mind that while we provide confidence levels, the models may occasionally generate incorrect or misleading information. Make sure to verify the information accordingly and we’d love to hear your feedback.

Code Inspector has a wide range of functionalities designed to enhance security, efficiency, and code quality. These processes are powered by machine learning models and state-of-the-art tools developed by our security experts.

  • Reused Code: Identifies vulnerabilities in reused smart contract code by generating a unique fingerprint for each contract and matching it against a database of known issues.

  • Vulnerable Dependencies: Notify when a OpenZeppelin Contracts dependency with a known vulnerability is used, providing you with the necessary information to address the issue.

  • Test Suggestions: Opportunities to apply fuzzing tests to functions, providing you with areas where further testing could prove beneficial.

  • External Call Safety: Safety of external calls, highlighting any instances that might pose a severity concern.

  • Standard Compatibility: Compatibility of your contracts with established standards, flagging potential compatibility issues.

  • Reentrancy Attack Vectors: Potential reentrancy attack vectors at both the file and function level, assigning these threats high-severity labels.

  • Code Readability: Missing docstrings in functions and misspelled words throughout the codebase, ensuring your code is as legible and understandable as possible.

  • Code Efficiency and Security Practices: Areas in your code where improvements can be made for better performance and highlights potential security risks, enabling you to optimize and secure your contracts more effectively.

Installation

Installation must be initiated from Defender. Installing the app directly from GitHub will not correctly set up the integration.

The installation process connects your Defender account and your GitHub repositories. Follow the following steps:

  1. Navigate to the Code Inspector page on Defender.

  2. Click on the Install Code Inspector button, which redirects you to Github.

  3. Select and approve the repositories to install the app.

  4. Generate your first report by creating or updating a pull request on a repository that has the app installed.

The installation is currently done solely through Defender, ensuring a seamless connection for the reports. Following the installation, no additional setup is required. If you encounter installation issues, refer to our Troubleshooting section for guidance.

Usage

Code Inspector is designed to streamline your code analysis workflow. Once installed, the app is triggered whenever a pull request (PR) is opened or a new commit is pushed to an existing PR in your GitHub repository. To avoid skipping the report, the PR must contain at least a modification to any Solidity file or the package.json file.

The app automatically generates a summary report for each new commit, which is posted as a comment in your PR. This summary report is continuously updated with the latest issues discovered in the most recent commit, and the commit hash is directly viewable in the report.

Along with the summary reports in PR comments, a detailed report for each commit is created and can be accessed on Defender, offering in-depth information on the identified issues and how to fix them.

If you wish to stop receiving reports for a specific repository, it’s as simple as navigating to the Code Inspector settings and removing the respective repository from the list.

Statuses

These are the possible statuses of reports:

  • Running: The report has been triggered, and it’s running.

  • Succeeded: The report has been successfully generated, and it’s available in Defender and Github.

  • Failed: The report has failed. Make sure that your repository contains valid Solidity files. If this issue persists, please get in touch.

  • Throttled: The report has been throttled as your tenant exceeded the Code Inpsector quota limit. If you would like to increase your quota, please get in touch.

  • Skipped: The report has been skipped. Check that the PR and/or commit contains at least one modification to a Solidity file or the package.json file.

Reports

Summary Report

The summary report provides a clear overview of potential vulnerabilities detected in the code during the review process. The report is conveniently categorized by process and severity level, making it easier to identify areas that need attention. You can navigate to the complete report on Defender via the provided link. Each report is tied to a specific commit, ensuring accurate tracking of changes and issues over time.

Summary Report

In this example, you can see the number of issues detected by Code Inspector, along with their respective severity levels. By clicking the link at the bottom of the report, you can view the full details of these vulnerabilities on Defender.

Issues

Full reports identify issues within your smart contracts using a broad range of rules. The rules cover many aspects, such as known vulnerabilities, best practices, code efficiency, and secure coding principles.

Full Report 1

Each issue is assigned a severity level based on the potential impact on the contract’s functionality and security. An explanation accompanies each flagged issue, articulating the reason for the concern.

Every issue has a suggested resolution tailored to improving your code quality and overall security. This might include recommendations to refine your code, modify visibility scopes, apply necessary mathematical checks, enhance documentation, or adhere to a specific Ethereum standard.

Depicted below is an example of a vulnerability detected in a dependency with a brief description of its potential impact. The specific dependency and its version are outlined, pinpointing where the problem exists.

Dependency Checker Report

To help you resolve these issues, recommendations on updates or patches that can address the vulnerabilities are provided along with the relevant advisory links for a more detailed understanding of the issue.

By reviewing and applying the proposed solutions in this report, you can enhance the robustness and reliability of your smart contracts, ensuring adherence to best practices and industry standards. This makes the audit process smoother and improves the preparedness of your contracts for successful deployment.

Standards

This feature introduces a new section in the report called Standards. This section provides insights into your contracts that implement interfaces from the OpenZeppelin Contracts library. For example, if you are using an IERC20, Code Inspector will check the implementation details and properties to ensure you are using this ERC correctly.

Detailed Checks

For each function and event defined in an interface, Code Inspector performs comprehensive checks to verify compliance with the standard. These checks include:

  • Signature: Ensures that the function or event signature matches the standard’s specification. Example: transfer(address,uint256)

  • Visibility: Checks that the visibility of functions and events adheres to the standard’s requirements. Example: external, public

  • Mutability: For functions, ensures that the mutability is correctly specified as per the standard. Example: view, pure

  • Return Type: Verifies that the return types of functions align with the expected types defined in the standard. Example returns (bool)

  • Parameter Names: Confirms that the parameter names are consistent with those defined in the standard, enhancing code readability and maintainability. Example: transfer(address recipient, uint256 amount)

  • Return Names: Ensures that the return variable names, where used, are consistent with the standard. Example: returns (bool success)

If any attribute of a function or event fails, the entire function or event is marked as failed. Additionally, if any function or event within an implementation fails, the entire implementation is considered non-compliant.

Configuration

You can configure repository-specific parameters for Code Inspector using a file called defender.config.json in the root directory. The structure of the file is separated into processes run by Code Inspector. Each process has a list of parameters that you can adjust to your needs. For example, you can specify which directories to scan, which is useful to prevent Code Inspector from analyzing test or script files written in Solidity.

Contract Inspector

Contract Inspector runs a set of rules to detect potential issues in your code. You can configure the following parameters:

  • enabled: ability to turn off the Contract Inspector. False meaning not to run, and true to run. (default: true)

  • scan_directories: list of directories to scan with paths starting from the root directory. default: ["."]

  • include_rules: list of rules to run. default: all rules.

  • exclude_rules: list of rules to not run. default: none.

Dependency Checker

Dependency Checker verifies that your dependencies are not vulnerable to known issues. You can configure the following parameters:

  • enabled: ability to turn off Dependency Checker. False meaning not to run, and true to run. (default: true)

Example

The following defender.config.json configuration file will disable Dependency Checker and run Contract Inspector on the src/contracts1 and src/contracts2 directories, excluding two rules (naming-convention and unused-state).

{
    "contract_inspector": {
        "enabled": true,
        "scan_directories": ["src/contracts1", "src/contracts2"],
        "exclude_rules": ["naming-convention", "unusued-state"]
    },
    "dependency_checker": {
        "enabled": false
    }
}

Assets

The Assets page allows you to manage your Code Inspector assets, supporting two types: Smart Contracts and GitHub repositories. When you install the Code Inspector GitHub app and select repositories, they will appear on this page. Additionally, you can create Smart Contract assets from addresses in your address book. Note that Smart Contract assets must be verified on Etherscan for this feature to work.

Smart Contract assets can be manually triggered for reports on the report page. GitHub assets can be triggered manually and automatically from new pull requests (PRs) and commits.

Code Assets

Settings

The Asset Settings page offers two main settings to manage how Defender handles asset security: Automatically Generate Report and Vulnerability Detection.

Automatically Trigger Report for Pull Requests

Automatically Generate Report, is specifically for GitHub repositories. When enabled, this setting ensures continuous monitoring by generating new reports automatically whenever a new pull request (PR) is opened or a new commit is pushed to a PR.

Active Vulnerability Detection and Notification

Active Vulnerability Detection and Notification provides a robust security measure by automatically scanning your assets for new vulnerabilities. This setting is applicable to both GitHub repositories and smart contracts. To enable this feature for Github repositories assets, you must activate the setting and select a specific branch to be monitored.

  • Automated Scanning: Leveraging Defender’s advanced smart contracts scanning capabilities, when our team becomes aware of a new vulnerability, whether disclosed or undisclosed, we promptly update our scanning algorithms to detect it. We then scan all assets configured to be monitored

  • Automated Notification: Once the automatic scanning is completed an automated system notification email will be sent to inform you whether the vulnerability was detected in your monitored assets. If detected, the notifications include relevant information tailored to the nature of the vulnerability.

  • Risk Mitigation: When detected, to aid in addressing and mitigating detected vulnerabilities, notifications may include suggestions for risk mitigation, providing actionable steps for administrators to protect their smart contracts and associated assets.

By enabling Active Vulnerability Detection and Notification for your assets, you can benefit from continuous, automated scanning and timely notifications, empowering you to respond quickly to new threats and maintain the security of your smart contracts and GitHub repositories. This proactive approach ensures that you can stay ahead of potential vulnerabilities and safeguard your code effectively.

Settings

The Settings page allows you to manage the permissions and access level of the Code Inspector. If you need to make changes to the repositories that the app has access to, a convenient link takes you directly to the GitHub settings page of the app, facilitating effortless repository management.

In the Github tab, you can globally suspend or uninstall the app, giving you complete control over its operation within your projects.

Code Inspector Github

Troubleshooting

Installation Issues

  • Installing the app outside Defender: Code Inspector must be installed via Defender. If you attempt to install it from elsewhere, the installation will not succeed. Ensure you’re logged in to your OpenZeppelin account and navigate to Code Inspector from Defender for a successful installation.

  • Code Inspector Access: Access to Code Inspector is required for a successful installation. If you find that you don’t have access and you think this is a mistake, contact OpenZeppelin support to get the necessary permissions.

Repository Size Issues

Errors related to analysis timeouts are often caused by large codebases. To mitigate this issue, it is recommended to use the scan_directories option in the defender configuration file to scope the analysis to relevant files only. By specifying which directories to include in the scan, the configuration file can significantly reduce processing times and prevent timeouts. For detailed instructions on setting up the configuration file, please refer to the Configuration section.

Rules

ID Description Severity

alert-uniswap-v2-router-liquidity-considerations

Identifies any instance of a Uniswap Router V2 addLiquidity call.

note

array-length-to-stack

Identifies when the length of an array can be written to the stack to save gas.

note

call-with-arbitrary-address-bytes

Identifies a potentially unsafe external call.

medium

chainlink-deprecated-functions

Identifies usage of chainlink’s deprecated functions.

medium

check-consistent-usage-of-msgsender-msgdata

Identifies usage of msg.sender or msg.data when _msgSender() or/and _msgData() are present

note

check-effect-interact

Identifies a possible violation of the check, effect and interact pattern.

ethtrust

check-erc4337-compatibility

Identifies if the contract may not be compatible with ERC-4337.

note

check-return-data-from-external-call

Identifies when the external call return data check is missing.

note

constants-not-using-proper-format

Identifies when a constant is not using the proper format.

note

dangerous-strict-equality

Identifies the use of strict equalities that can cause a Gridlock.

medium

default-values-assigned

Identifies an instance of a variable initialized to its default value.

note

delegatecall-to-arbitrary-address

Identifies when an there is a delegatecall or call code to an arbitrary address.

high

delegatecall-usage

Identifies an instance of delegatecall.

ethtrust

different-pragma-directives

Identifies whether different Solidity versions are used.

low

disableinitializers-not-called-in-implementation-constructor

Identifies if _disableInitializers() is not being called in the constructor of an Initializable contract

note

doc-code-mismatch-model

Identifies a possible docstrings and code mismatch.

low

duplicated-import

Identifies duplicated imports.

note

exact-balance

Identifies whether a balance is compared to an exact value.

ethtrust

external-call-reentrancy-attack-vector

Identifies external calls as a possible vector for a reentrancy attacks.

note

fallback-with-return-value

Identifies if there are fallback functions with return values.

note

floating-pragma

Identifies pragma directives that do not specify a particular, fixed version of Solidity.

low

function-init-state-variable

Identifies when a state variable is initialized by a function.

note

function-level-access-control-model

Identifies a possible access control attack vector on a function.

high

function-level-reentrancy-model

Identifies a possible reentrancy attack vector on a function.

high

function-visibility-too-broad

Identifies if function visibility is unnecessarily broad.

note

gas-limit-on-call

Identifies when an external call has a hard-coded gas limit.

low

hashing-dynamic-values

Identifies a hashing of a packed encoded dynamic value.

ethtrust

identify-hardhat-console-import

Identifies a hardhat console import.

note

identify-to-do-comments

Identifies todo comments in the code.

note

inconsistent-order-contract

Identifies when a contract has a inconsistent order.

note

inconsistent-use-named-returns

Identifies inconsistent usage of named returns within a codebase.

note

incorrect-format-onERC721Received

Identifies when a contract includes the onERC721Received function and it has an incorrect format.

note

incorrect-modifier

Identifies an incorrect definition of a modifier.

medium

incremental-update-optimization

Identifies the use of i` (rather than `i) to save gas in for loop headers.

note

indecisive-license

Identifies when a file has multiple SPDX licenses.

note

int-negative-evaluation-overflow

Identifies when additive inverse of an int variable is evaluated.

note

lack-of-gap-variable

Identifies when an upgradeable contract does not have a gap variable.

low

lack-of-indexed-event-parameters

Identifies when a lack of indexed event parameter.

note

lack-of-security-contact

Identifies when a contract does not have a security contact.

note

lack-of-spdx-license-identifier

Identifies when a lack of SPDX license identifier.

note

lock-ether

Identifies any instance of locked ETH within a contract.

high

memory-side-effect-assembly

Identifies when some code may be vulnerable to a Solidity compiler vulnerability.

medium

missing-docstrings

Identifies when a function is missing docstrings.

low

missing-initializer-modifier

Identifies when a function is missing the initializer modifier.

low

missing-mapping-named-parameters

identifies when a mapping is missing named parameters

note

missing-return

Identifies when a function is missing the return statement.

low

misuse-boolean-literal

Detects the misuse of a Boolean literal (used in complex expressions or as conditionals).

medium

msg-value-loop

Identifies usage of msg.value inside a loop.

note

multiple-contracts-per-file

Identifies multiple contract declarations per file.

note

name-reused

Identifies in a codebase when two or more contracts have the same name.

note

non-explicit-imports

Identifies a non-explicit import.

note

not-operator-assembly

Identifies usage of the not operator inside assembly code because it functions differently than in other languages.

note

outdated-solidity-version

Identifies a Solidity file with an outdated Solidity version.

note

overriding-state-values-in-constructor

Identifies cases where state variables are explicitly set to values within a contract but are overwritten by the constructor.

note

possible-incorrect-abi-decode

Identifies the potential for incorrect ABI decoding.

note

possible-return-bomb

Identifies a possible vector for a return bomb attack.

note

pragma-spans-breaking-changes

Identifies a Solidity file with pragma that spans versions of solidity where breaking changes may have been introduced.

low

precision-loss-div-before-mul

Identifies possible precision loss due to division before multiplication

note

redundant-safemath-library

Identifies a redundant use of SafeMath library.

note

replace-revert-strings-custom-errors

Identifies when a revert string could be replaced by a custom error.

note

require-instead-of-revert

Identifies when a require statement does not check for any conditions.

low

require-missing-message

Identifies when an error message is missing from the require statement.

low

require-multiple-conditions

Identifies a require statement with multiple conditions.

low

revert-missing-message

Identifies when a revert statement is missing the error message.

low

selfdestruct-usage

Identifies an instance of selfdestruct.

ethtrust

state-updated-without-event

Identifies if a function is updating the state without an event emission.

note

state-var-visibility-not-explicitly-declared

Identifies when the visibility of a state variable that has not been explicitly declared.

note

sushiswap-callback-attack

Identifies possible attacks on sushiswap callback where a fake pool address can pass authorization check.

note

swapped-arguments-function-call

Identifies when the arguments of function call have been swapped.

note

too-many-digits

Identifies a literal number with many digits.

note

transferfrom-dangerous-from

Identifies usage of transferFrom with from parameter not being a msg.sender.

high

unchecked-call-success

Identifies when the external call fail check is missing.

ethtrust

unchecked-increment

Identifies that an incremental update is not wrapped in an unchecked block.

note

unchecked-keyword

Identifies unchecked code inside a function.

note

unchecked-math

Identifies a potentially unsafe usage of unchecked math.

high

unicode-direction-control

Identifies the use of unicode direction control character.

ethtrust

unnecessary-assignment

Identifies an unnecessary assignment of a variable.

note

unnecessary-cast

Identifies an unnecessary cast.

note

unsafe-abi-encoding

Identifies any use of unsafe ABI encoding.

low

unsafe-mint-ERC721

Identifies if a _mint function is used instead of _safeMint in ERC721 context.

note

unused-arguments

Identifies an unused function argument.

note

unused-enum

Identifies an unused enum.

note

unused-error

Identifies an unused error.

note

unused-event

Identifies an unused event.

note

unused-function

Identifies an unused function with internal or private visibility.

note

unused-imports

Identifies an unused import.

note

unused-named-returns

Identifies an unused named return variable.

note

unused-state-variable

Identifies an unused state variable.

note

unused-struct

Identifies an unused struct.

note

use-of-transfer-send

Identifies instance of transfer or send.

low

use-of-uint-instead-of-uint256

Identifies if an int/uint is used instead of int256/uint256.

note

variable-could-be-constant

Identifies variables that could be declared as constant.

note

variable-could-be-immutable

Identifies variables that are only ever set in the constructor and could be immutable.

note

void-constructor-call

Identifies the call to a constructor that is not implemented.

low