A malicious operator will control consensus without risking stake (stake-exit lag exploit)
Summary
The non-atomic nature of setSigVerifier and commitValSetHeader will cause a potential loss of security guarantees for networks as a malicious operator can manipulate validator sets after unstaking their funds, avoiding slashing penalties.
Root Cause
In Settlement contract the design choice to separate setSigVerifier and commitValSetHeader functions (latter being public) is a mistake as it allows for a time gap between validator selection and header commitment. This creates a window where an operator can withdraw their stake while still maintaining their voting power.
Specifically, commitValSetHeader in Settlement is marked as public:
While setSigVerifier is a separate function:
Attack Path
Epoch 1:
- A malicious operator deposits a large amount of stake to their vault, ensuring it exceeds the
quorumThresholdfor voting power. - The off-chain relay calculates voting powers, creates a
sigVerifierusing validators belonging to the malicious operator, and callssetSigVerifierto assign these validators for the next epoch. - Near the end of Epoch, the operator calls
withdrawon their vault to initiate the withdrawal of their stake.
Epoch 2:
- The operator immediately calls
claimon their vault to retrieve all their withdrawn stake, effectively removing their financial exposure. - Despite having withdrawn their stake, their voting power is active in the system's state for a short time-span.
- The operator can craft their own proof using their validators' private keys, which will pass verification since they had enough voting power.
- When the operator submits this crafted proof to
commitValSetHeader, it will be accepted by the system, allowing the operator to control consensus without any stake at risk.
Impact
The network suffers a complete compromise of its security model. The malicious operator can perform any validator action (such as approving invalid transactions or censoring valid ones) without having any stake at risk of being slashed. This fundamentally breaks the economic security assumptions of the protocol, which relies on validators having skin in the game to behave honestly.
Mitigation
Redesign the commitValSetHeader function to be internal (_commitValSetHeader), and create a new public function that handles both setting the signature verifier (optional) and committing the header in a single atomic transaction.
Alternatively apply checkPermission to commitValSetHeader so it can only be executed by the Network's relay service.