Corrupt Commitments: Proposer Equivocation Bug in Helix MEV Relay

Introduction

In April 2023, a malicious proposer tricked Ultrasound’s relay into revealing the contents of a block while committing to a conflicting, invalid block. The attacker performed an unbundling attack, reordering transactions against the builder’s will and sandwiching traders, that profited between $20 and $30 million. On November 23, 2024, we responsibly disclosed a variant of this attack on Titan Relay introduced by support for the Deneb hard fork.

To support the Deneb hard fork, Flashbots upgraded its relay implementation and added a check on the integrity of the KZG commitments, a cryptographic scheme to commit to a value that can later be revealed, within the proposer’s response. Titan Relay’s alternative relay implementation, Helix, missed this key validation, which would have allowed trusted actors to attempt unbundling without the risk of slashing.

Relays implemented three safeguards following the 2023 incident:

  • validate the integrity of the signed header,
  • require local beacon nodes to verify the signed beacon block before broadcasting it,
  • wait 1 second before sending the unblinded block back to a propose.

Because of the local verification done before the broadcast performed by Lighthouse’s implementation of the publishBlockV2 Beacon API, Titan’s production environment would have prevented untrusted proposers from receiving the block if they attempted the attack that follows.

Proposer-builder Separation

Proposer-builder separation allows beacon chain validators to outsource their block building to specialized entities, builders, who provide the validator a block via a trusted intermediary, relays, when it is the validator’s turn to propose i.e. they are a proposer. Builders trust the relay to keep the contents of blocks confidential until the proposer has committed to proposing the block by signing its header.

If the proposer can leak the contents of the block prematurely, they may maliciously alter the order of transactions the builder provided. For instance, builders may offer services to traders that wish to keep their orders private so it won’t be front-run and affect the price at which the trader purchases a given asset.

Building an alternate block is latency-sensitive as proposers have a strict window of time to gossip and receive sufficient attestations. Relays have attempted to deter proposers from risking their validator rewards by making it likely they will miss their slot if they do not immediately propose the builder’s original blocks due to the relay’s delayed response. Further, relays ensure proposers will get slashed for proposing two blocks at the same height by broadcasting the block the proposer initially committed to.

Builder, Beacon, and Blob

During a proposer's slot, it may request a payload from a relay. It will sign and thereby commit to proposing this block without seeing the entire payload, e.g., its transactions, which is why it is referred to as “blinded”. Then, the proposer will send the signed, blinded beacon block back to the relay and receive an “unblinded” block”, which reveals its transaction contents, in return.

After the April 2023 incident, relays introduced a delay in their response to the proposer, during which they will gossip the block and blob sidecars, if any, to the beacon chain, giving the block time to disseminate and reduce the likelihood that a proposer can build and propose a conflicting block. However, this delay only gives the relay an advantage if the block and blob sidecars are valid because peers will reject and not process invalid proposals.

When a beacon node receives a blob sidecar, it will reject it if the KZG commitments, which are polynomial commitments to blobs of data, do not correspond to the sidecar’s blob contents, as stated in the specification:  

[REJECT] The sidecar's blob is valid as verified by verify_blob_kzg_proof(blob_sidecar.blob, blob_sidecar.kzg_commitment, blob_sidecar.kzg_proof).

Additionally, when a beacon node receives a block, it will check that it has seen or can request associated blobs. If a blob sidecar is rejected, the blobs will not be available. Thus, being able to send invalid commitments from the relay defeats any advantage gained by propagating it as beacon nodes will reject the block for containing unavailable data.

# [New in Deneb:EIP4844]  # Check if blob data is available      assert is_data_available(hash_tree_root(block), block.body.blob_kzg_commitments)

Corrupt Commitments

The validations performed on the KZG commitments in Helix only require an attacker to ensure that the length of blobs and commitments must be the same in their submitBlindedBlock request. Instead of sending the correctly signed beacon block back to the relay, a malicious proposer could manipulate the commitments and attempt to build a more profitable block from the transactions the relay was tricked into providing.

Flow diagram of the attack

While the relay's validate_header_equality method verifies that the contents of the signed execution payload header are equivalent to what the builder supplied, it does not bind the proposer to the KZG commitments (notice their absence in the Deneb fields below). Thus, invalid KZG commitments can be provided and still pass signature verification and header validation.

class ExecutionPayloadHeader(Container):  
    # Execution block header fields  
    parent_hash: Hash32  
    fee_recipient: ExecutionAddress  
    state_root: Bytes32  
    receipts_root: Bytes32  
    logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]  
    prev_randao: Bytes32  
    block_number: uint64  
    gas_limit: uint64  
    gas_used: uint64  
    timestamp: uint64  
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]  
    base_fee_per_gas: uint256  
    # Extra payload fields  
    block_hash: Hash32  # Hash of execution block  
    transactions_root: Root  
    withdrawals_root: Root  
    blob_gas_used: uint64  # [New in Deneb:EIP4844]  
    excess_blob_gas: uint64  # [New in Deneb:EIP4844]  

The relay transparently forwards body.blob_kzg_commitments (which is controlled by the proposer) to beacon clients rather than the original commitments provided by the builder. Untrusted proposers would not receive an unblinded block as the beacon client validation will error and cause the server to reply with an error message.

On the other hand, the relay will unblind the block and send the trusted proposer back the entire payload even if an error occurs. Having received the unblinded block, a malicious proposer can re-order its contents and propose a second block with sandwiched transactions. Because the relay's block includes invalid KZG commitments, peers will reject it during data availability checks, giving the malicious proposer a better chance its block is finalized.

Timeline

  • Nov 23 6:04 AM UTC Bug report sent to Gattaca’s email
  • Nov 25 11:36 AM UTC Gattaca replies and asks for Telegram contact
  • Nov 25 6:07 PM UTC Gattaca sends an already deployed patch that fixes the issue

Conclusion

A malicious, trusted proposer could have signed a blinded beacon block and provided the relay with invalid KZG commitments to receive the unblinded payload, proposing an alternative block that is profitable for them which will win out against the relay’s invalid block. The fix enforces that the KZG commitments sent by the proposer must be equivalent to what the relay received from the builder, as the Flashbots implementation does.

We would like to thank Gattaca for their responsiveness during our disclosure, as well as the bug bounty they offered as reward.

// Blog

// Blog

// Blog

// Blog

// Blog

// Blog

// Blog

// Blog

// Blog

// Blog

// Blog

// Blog

// Blog

// Blog

Research

Cosmos IBC Reentrancy Infinite Mint

In this article, we describe a vulnerability in ibc-go, the reference implementation of the Cosmos Inter-Blockchain Communication (IBC) protocol. A reentrancy vulnerability during the handling of timeout messages could have allowed an attacker to mint an infinite amount of IBC tokens on affected Cosmos chains.

Research

Circle's CCTP Noble Mint Bug

We privately disclosed a vulnerability to Circle via their bug bounty program. The vulnerability could have been exploited by circumventing the CCTP message sender verification process to mint fake USDC tokens on Noble.

View All Posts