Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update: improve unhandled initializers in unprotected-upgrade detector #2203

Merged
merged 6 commits into from
Jun 4, 2024

Conversation

vovikhangcdv
Copy link
Contributor

@vovikhangcdv vovikhangcdv commented Oct 25, 2023

What PR for

unprotected-upgrade only detects function name initialize as initializer. It will increase false negatives because of missing proper initializers.

What PR does

  • Count any function with an initializer or reinitializer modifier as an initializer.
  • Remove ambiguous relation between _is_upgradeable and _is_upgradeable_proxy. The _is_upgradeable should not be excluded by _is_upgradeable_proxy. For example, just because the contract name has proxy in its name, detectors should not miss the bug (false negative).

Summary by CodeRabbit

  • New Features

    • Introduced new smart contracts AnyInitializer and Reinitializer with initialization and self-destruct functionalities across various versions.
    • Added reinitializer modifier to Initializable contract to handle versioned reinitialization.
  • Bug Fixes

    • Modified _initialize_functions to filter functions with specific modifiers for enhanced security.
  • Tests

    • Added new test scenarios for UnprotectedUpgradeable detectors to validate the security of upgradeable contracts.

@vovikhangcdv
Copy link
Contributor Author

I just added: Remove ambiguous relation between _is_upgradeable and _is_upgradeable_proxy.

The _is_upgradeable should not be excluded by _is_upgradeable_proxy. For example, just because the contract name has proxy in its name, detectors should not miss the bug (false negative).

@vovikhangcdv
Copy link
Contributor Author

hi there, any update? @@
sorry to ping reviewers @montyly @0xalpharush @smoelius

Copy link

coderabbitai bot commented May 9, 2024

Walkthrough

Walkthrough

The recent updates involve modifications and additions across multiple files related to the Slither framework and test environments for detecting vulnerabilities in upgradeable smart contracts. Changes include altering the initialization and protection mechanisms of smart contracts, refining detection capabilities for unprotected upgradeable functions, and introducing new test cases and contracts to enhance the robustness of security assessments.

Changes

File Path Change Summary
slither/core/declarations/contract.py Removed conditional check for is_upgradeable_proxy in is_upgradeable method.
slither/detectors/statements/unprotected_upgradeable.py Modified _initialize_functions to filter functions by initializer or reinitializer modifiers.
Various tests/e2e/detectors/snapshots/ files Introduced new test files for AnyInitializer and Reinitializer contracts across different Solidity versions, highlighting the lack of protection in initialize functions and potential for unauthorized deletion.
Various tests/e2e/detectors/test_data/unprotected-upgrade/ files across versions Added and modified contracts AnyInitializer and Reinitializer with initialization and self-destruct functions, alongside the addition of reinitializer modifiers in Initializable contracts.
tests/e2e/detectors/test_detectors.py Added tests for UnprotectedUpgradeable detector with various contracts and versions.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Out of diff range and nitpick comments (5)
tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Initializable.sol (1)

6-8: The reinitializer modifier implementation is correct. Consider adding a comment explaining the unused version parameter, if it's intended for future use or external checks.

tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol (1)

6-8: The reinitializer modifier implementation is correct. Consider adding a comment explaining the unused version parameter, if it's intended for future use or external checks.

tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol (1)

6-8: The reinitializer modifier implementation is correct. Consider adding a comment explaining the unused version parameter, if it's intended for future use or external checks.

slither/core/declarations/contract.py (2)

Line range hint 967-967: Undefined name 'Event' used in type hint.

- def get_event_from_signature(self, event_signature: str) -> Optional["Event"]:
+ def get_event_from_signature(self, event_signature: str) -> Optional["EventContract"]:

Line range hint 977-977: Undefined name 'Event' used in type hint.

- def get_event_from_canonical_name(self, event_canonical_name: str) -> Optional["Event"]:
+ def get_event_from_canonical_name(self, event_canonical_name: str) -> Optional["EventContract"]:
Review Details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits Files that changed from the base of the PR and between 4645ba5 and 1f15416.
Files ignored due to path filters (10)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol-0.4.25.zip is excluded by !**/*.zip
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol-0.4.25.zip is excluded by !**/*.zip
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol-0.5.16.zip is excluded by !**/*.zip
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol-0.5.16.zip is excluded by !**/*.zip
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol-0.6.11.zip is excluded by !**/*.zip
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol-0.6.11.zip is excluded by !**/*.zip
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol-0.7.6.zip is excluded by !**/*.zip
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol-0.7.6.zip is excluded by !**/*.zip
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol-0.8.15.zip is excluded by !**/*.zip
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol-0.8.15.zip is excluded by !**/*.zip
Files selected for processing (28)
  • slither/core/declarations/contract.py (1 hunks)
  • slither/detectors/statements/unprotected_upgradeable.py (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_AnyInitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_Reinitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_AnyInitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_Reinitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_AnyInitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_Reinitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_AnyInitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_Reinitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_AnyInitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_Reinitializer_sol__0.txt (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Initializable.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Initializable.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol (1 hunks)
  • tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol (1 hunks)
  • tests/e2e/detectors/test_detectors.py (5 hunks)
Additional Context Used
Ruff (2)
slither/core/declarations/contract.py (2)

967-967: Undefined name Event


977-977: Undefined name Event

Additional comments not posted (36)
tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Initializable.sol (1)

2-4: The initializer modifier implementation looks good.

tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol (1)

2-4: The initializer modifier implementation looks good.

tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol (1)

2-4: The initializer modifier implementation looks good.

tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol (2)

6-9: The anyName function correctly implements the initializer pattern, ensuring that it can only be called once when the owner is not set.


11-13: The kill function is correctly protected to ensure only the owner can trigger it, which is crucial for sensitive operations like selfdestruct.

tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol (2)

6-9: The initialize function correctly uses the reinitializer modifier to demonstrate versioned reinitialization, ensuring it can only be called once when the owner is not set.


11-13: The kill function is correctly protected to ensure only the owner can trigger it, which is crucial for sensitive operations like selfdestruct.

tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol (2)

6-9: The anyName function correctly implements the initializer pattern with the updated owner type to address payable, suitable for newer Solidity versions.


11-13: The kill function is correctly protected to ensure only the owner can trigger it, which is crucial for sensitive operations like selfdestruct.

tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol (2)

6-9: The initialize function correctly uses the reinitializer modifier to demonstrate versioned reinitialization with the updated owner type to address payable, suitable for newer Solidity versions.


11-13: The kill function is correctly protected to ensure only the owner can trigger it, which is crucial for sensitive operations like selfdestruct.

tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol (2)

6-9: The anyName function correctly implements the initializer pattern with the explicit use of payable for the owner assignment, enhancing clarity in newer Solidity versions.


11-13: The kill function is correctly protected to ensure only the owner can trigger it, which is crucial for sensitive operations like selfdestruct.

tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol (2)

6-9: The anyName function correctly implements an initializer pattern by ensuring it can only be executed once and setting the contract's owner.


11-13: The kill function includes appropriate security checks to ensure that only the owner can destroy the contract.

tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol (2)

6-9: The anyName function correctly implements an initializer pattern by ensuring it can only be executed once and setting the contract's owner.


11-13: The kill function includes appropriate security checks to ensure that only the owner can destroy the contract.

tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol (2)

6-9: The initialize function correctly implements a re-initializer pattern by potentially allowing re-execution under controlled conditions and setting the contract's owner.


11-13: The kill function includes appropriate security checks to ensure that only the owner can destroy the contract.

tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol (2)

6-9: The initialize function correctly implements a re-initializer pattern by potentially allowing re-execution under controlled conditions and setting the contract's owner.


11-13: The kill function includes appropriate security checks to ensure that only the owner can destroy the contract.

tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol (2)

6-9: The initialize function correctly implements a re-initializer pattern by potentially allowing re-execution under controlled conditions and setting the contract's owner.


11-13: The kill function includes appropriate security checks to ensure that only the owner can destroy the contract.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_Reinitializer_sol__0.txt (1)

1-1: The snapshot accurately describes the vulnerabilities in the Reinitializer contract, highlighting the unprotected initialize function and the potential for unauthorized contract destruction.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_Reinitializer_sol__0.txt (1)

1-1: The snapshot accurately describes the vulnerabilities in the Reinitializer contract, highlighting the unprotected initialize function and the potential for unauthorized contract destruction.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_Reinitializer_sol__0.txt (1)

1-1: The snapshot accurately describes the vulnerabilities in the Reinitializer contract, highlighting the unprotected initialize function and the potential for unauthorized contract destruction.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_Reinitializer_sol__0.txt (1)

1-1: Description accurately outlines the test scenario for Reinitializer with unprotected initialization functions.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_AnyInitializer_sol__0.txt (1)

1-1: Description accurately outlines the test scenario for AnyInitializer with unprotected initialization functions.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_Reinitializer_sol__0.txt (1)

1-1: Description accurately outlines the test scenario for Reinitializer with unprotected initialization functions.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_AnyInitializer_sol__0.txt (1)

1-1: Description accurately outlines the test scenario for AnyInitializer with unprotected initialization functions.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_AnyInitializer_sol__0.txt (1)

1-1: Description accurately outlines the test scenario for AnyInitializer with unprotected initialization functions.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_AnyInitializer_sol__0.txt (1)

1-1: Description accurately outlines the test scenario for AnyInitializer with unprotected initialization functions.

tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_AnyInitializer_sol__0.txt (1)

1-1: Description accurately outlines the test scenario for AnyInitializer with unprotected initialization functions.

tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol (1)

9-11: Addition of the reinitializer modifier aligns with the PR's objectives to enhance detection capabilities.

slither/detectors/statements/unprotected_upgradeable.py (1)

55-62: The modifications to _initialize_functions correctly expand the criteria for detecting initializer functions. Good use of list comprehensions and filtering.

tests/e2e/detectors/test_detectors.py (1)

Line range hint 941-1050: The new test configurations for UnprotectedUpgradeable detector are correctly added for multiple Solidity versions. This ensures comprehensive testing across different environments.

Comment on lines +9 to +11
modifier reinitializer(uint64 version) {
_;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider implementing logic in the reinitializer modifier or provide a comment explaining its intended use.

@0xalpharush 0xalpharush merged commit dde3378 into crytic:dev Jun 4, 2024
74 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants