Timelock can be bypassed #263
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
Handle
WatchPug
Vulnerability details
The purpose of a Timelock contract is to put a limit on the privileges of the
governor
, by forcing a two step process with a preset delay time.However, we found that the current implementation actually won't serve that purpose as it allows the
governor
to execute any transactions without any constraints.To do that, the current governor can call
Timelock#setGovernor(address _governor)
and set a newgovernor
effective immediately.And the new
governor
can then callTimelock#setDelay()
and change the delay to0
, also effective immediately.The new
governor
can now use all the privileges without a delay, including granting minter role to any address and mint unlimited amount of MALT.In conclusion, a Timelock contract is supposed to guard the protocol from lost private key or malicious actions. The current implementation won't fulfill that mission.
https://github.com/code-423n4/2021-11-malt/blob/c3a204a2c0f7c653c6c2dda9f4563fd1dc1cecf3/src/contracts/Timelock.sol#L98-L105
https://github.com/code-423n4/2021-11-malt/blob/c3a204a2c0f7c653c6c2dda9f4563fd1dc1cecf3/src/contracts/Timelock.sol#L66-L77
Recommendation
Consider making
setGovernor
andsetDelay
only callable from the Timelock contract itself.Specificaly, changing from
onlyRole(GOVERNOR_ROLE, "Must have timelock role")
torequire(msg.sender == address(this), "...")
.Also, consider changing
_adminSetup(_admin)
inTimelock#initialize()
to_adminSetup(address(this))
, so that all roles are managed by the timelock itself as well.The text was updated successfully, but these errors were encountered: