The tree proxy architecture, designed to facilitate the upgrade of multiple branches in the same release version, faces a critical compatibility issue with OpenZeppelin's Initializable design. This problem will arise in future upgrades because of the shared INITIALIZABLE_STORAGE slot. This incompatibility results in failed upgrades, making the pattern unsuitable for current use with the OpenZeppelin Initializable library.
The root cause of the vulnerability is the misuse of the Initializable library, where multiple initializables are expected while ONLY one INITIALIZABLE_STORAGE slot is used.
Let us walk through the issue with the following scenario:
Alice, a developer, implements the tree proxy pattern using OpenZeppelin's Initializable library for managing upgradeable contracts.
After the initial deployment, Alice has freshly developed more branches and attempts to add those in the same release version using the initialize function.
Since the RootProxy manages all branches with the same slot of INITIALIZABLE_STORAGE, it is impossible to call initialize on them outside of construction because the INITIALIZABLE_STORAGE._initialed state has been set to 1 after the initial deployment of the RootProxy and address(RootProxy).code.length is not 0 anymore which makes both initialSetup and construction below not being met. This will cause Alice's call to upgrade to fail with InvalidInitialization error.
Alice tries to workaround the issue by calling the reinitialize(version) function but still fails due to this version condition as it strictly requires the version input has to be incremented after each calls. Which means each new/upgraded branch version has to be unique even if they belong to the same release.
Incrementing the version for each new branch contradicts versioning semantics, making upgrades infeasible.
Add following code to 2024-07-zaros/test/integration/tree-proxy/upgrade-branch/upgrade/upgradeBranch_initializables.t.sol and run with forge test -vvv --mt test_addNewInitializables
The PASS result will confirm the upgradability issue.
This vulnerability has a Medium severity because it fundamentally breaks the upgrade process in the tree proxy pattern. The inability to (re)initialize branches with the same version prevents seamless upgrades, potentially leading to significant operational disruptions and increased complexity in version management. This will also reduce the number of potential adaptations of the Tree Proxy architecture.
Foundry test
To mitigate this critical issue, consider customizing the Initializable library to make the INITIALIZABLE_STORAGE slot unique for each new initializable branch, ensuring the Root does not use a conflicted slot. Alternatively, develop a new Initializable pattern compatible with the Tree Proxy pattern.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.