Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Public Access to LevelTwo::graduate Allows Unauthorized Reinitializer

Summary

The LevelTwo::graduate function is marked with the reinitializer(2) modifier and is publicly accessible without any access control. This means any external user can invoke it once, consuming the contract's version 2 reinitialization slot. As a result, the legitimate contract owner (e.g., the principal) may be permanently prevented from executing critical upgrade-time logic, such as setting new variables or distributing funds.


Vulnerability Details

// @audit-issue Public graduate() function lacks access control, allowing any user to consume reinitializer(2)
function graduate() public reinitializer(2) {
// no access restriction
// @> Anyone can trigger this, permanently locking out reinitialization logic
}

Issue Explanation

  1. Unrestricted Access
    Since the function is public and has no onlyPrincipal or equivalent modifier, any address can call it.

  2. Consumes reinitializer(2)
    The reinitializer(2) modifier ensures that this function can only be executed once. If a malicious user calls it first, the contract is marked as "initialized to version 2", blocking any future reinitializer(2) logic.

  3. Breaks Upgrade Safety
    This may prevent proper initialization of new state variables or distribution of resources introduced in LevelTwo, leading to broken business logic and stuck funds.


Impact

  • Denial of Initialization: Legitimate parties are blocked from performing upgrade-time setup.

  • Potential Logic Incompleteness: Contract may remain in a partially-upgraded, unusable state.

  • System Integrity Loss: Future UUPS upgrades or state transitions may silently fail.


Tools Used

  • Manual Code Review


Recommendations

Add appropriate access control (e.g., onlyPrincipal) to restrict graduate() execution to authorized parties only:

modifier onlyPrincipal() {
require(msg.sender == principal, "Not authorized");
_;
}
function graduate() public reinitializer(2) onlyPrincipal {
// upgrade-time logic here
}

Alternatively, consider making graduate() internal if it is only intended to be called within another controlled flow.


Updates

Lead Judging Commences

yeahchibyke Lead Judge 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

failed upgrade

The system doesn't implement UUPS properly.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.