OpenZeppelin Governor Smart Contract Denial of Service Flaw
Coinspect found a vulnerability in the latest version of the Governor smart contract provided by OpenZeppelin. This vulnerability would allow an attacker to halt proposals sent to a governance protocol using the latest version of OpenZeppelin’s suite.
The vulnerability was introduced on Jan 26, 2023 and was part of the latest OZ release 4.9.0.
We reported the issue to OpenZeppelin via their bug bounty program on May 30 (like we did when we found Arbitrum’s issue in governance). OpenZeppelin acknowledged the problem quickly and after discussion and collaboration on the fix, it was released on version 4.9.1 of OpenZeppelin’s contracts.
What made the attack possible was the exposure of the cancel
function, which used to be internal
:
/**
* @dev See {IGovernor-cancel}.
*/
function cancel(uint256 proposalId) public virtual override {
require(state(proposalId) == ProposalState.Pending, "Governor: too late to cancel");
require(_msgSender() == _proposals[proposalId].proposer, "Governor: only proposer can cancel");
_cancel(proposalId);
}
The exposed cancel
method allows a malicious user to disrupt the governance proposal process by leveraging the way proposalId
s are calculated. There are two participants involved in the attack: an attacker
that does not want a proposal to pass and a proposer
that wants to submit a new proposal.
- The
proposer
sends their proposal to the network - The
attacker
frontruns their transaction, submitting the exact same proposal - As soon as possible, the
attacker
callscancel
on their proposal
See that the attacker
can continue performing the attack as long as they wish. Each time the cost is only two transactions, one of which must be a frontrun.
This cost is negligible for proposals which seriously impact the working of a protocol.
OpenZeppelin decided to address the issue by allowing proposers to append their address to the end of a proposal’s description. If a proposer does this,
the proposalId
is now linked to their address. An attacker
can still try to frontrun the proposal, but they would get a different proposalId
. It is important
to note that proposers are allowed but not forced to do this, so an unaware proposer is still be vulnerable to the attack. Frontends for governance protocols will
also still use the vulnerable path in the code until they update.
Read the Security Advisory.
Smart Contract Governance Security
At Coinspect, we are dedicated to the security of decentralized systems and can assist in auditing your smart contract protocols and enforcing safeguards. Reach out to us today.