Open code423n4 opened 3 years ago
The warden has identified an exploit that allows to sidestep the delay for the timelock, effectively bypassing all of the timelock's security guarantees. Because of the gravity of this, I agree with the high risk severity.
Mitigation can be achieved by ensuring that all operations run under a time delay
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.