Assessment reports>Blobstream X>Critical findings>End block's header hash is unconstrained for a subchain proof
Category: Coding Mistakes

End block's header hash is unconstrained for a subchain proof

Critical Severity
Critical Impact
High Likelihood

Description

The output for prove_subchain circuit contains the following values.

MapReduceSubchainVariable {
    is_enabled: is_batch_enabled,
    start_block: batch_start_block,
    start_header: batch_start_header_hash,
    end_block: batch_end_block,
    end_header: batch_end_header_hash,
    data_merkle_root,
}

The end_header is the header hash of the last block in the subchain. However, the value it contains (i.e., batch_end_header_hash) is taken directly from the input and left completely unconstrained.

Impact

A malicous prover can supply an arbitrary value for the end header, which allows for the Blobstream state to differ from the on-chain state.

Recommendations

The loop in prove_subchain calculates the header for each block in the chain and verifies chain integrity using Merkle proofs.

curr_header = last_block_id_proof_root;

At the end of the loop, curr_header will contain the hash of the last block, and it should be asserted that this hash is equal to the value being returned.

let end_hash_matches_calculated_hash = self.is_equal(batch_end_header_hash, curr_header);
self.assert_is_equal(end_hash_matches_calculated_hash, true_bool);

Remediation

This issue has been acknowledged by Succinct, and a fix was implemented in the following commit: .

Zellic © 2024Back to top ↑