VYPR
Medium severity5.3GHSA Advisory· Published May 21, 2026· Updated May 21, 2026

nimiq-blockchain: Genesis batch set request

CVE-2026-46543

Description

Impact

A remote peer can crash any full node by sending a RequestBatchSet message containing the genesis block's hash. The handler calls get_epoch_chunks which iterates backwards through macro blocks using Policy::macro_block_before. When it reaches the genesis block number, macro_block_before panics with "No macro blocks before genesis block".

Patches

The patch for this vulnerability is formally released as part of v1.5.0.

Workarounds

No Workaround, although requesting the genesis batch set is not used during normal operation.

Resources

See PR.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A remote peer can crash any Nimiq full node by sending a RequestBatchSet message with the genesis block hash, triggering a panic in get_epoch_chunks.

Root

Cause

The vulnerability exists in the RequestBatchSet message handler of the Nimiq core-rs-albatross node software. When a full node receives a RequestBatchSet message containing the genesis block's hash, the handler calls get_epoch_chunks, which iterates backwards through macro blocks using Policy::macro_block_before. Once the iteration reaches the genesis block number, macro_block_before panics with the message "No macro blocks before genesis block" [1].

Exploitation

An attacker can exploit this vulnerability remotely by sending a specially crafted RequestBatchSet message to any full node. No authentication or special privileges are required, and the attack does not require user interaction. Since RequestBatchSet is a valid network message, the vulnerable code path is reachable from any remote peer. While requesting the genesis batch set is not part of normal operation, the lack of input validation allows this edge case to trigger a crash [2][4].

Impact

Successful exploitation results in a denial of service (DoS) condition: the targeted full node crashes immediately upon processing the malicious message. This impacts the availability of the node, disrupting its ability to participate in the network, validate transactions, and serve data to other peers. The CVSS score of 7.5 (High) reflects the remote attack vector, low complexity, and high availability impact [4].

Mitigation

The vulnerability is patched in Nimiq core-rs-albatross version 1.5.0, which includes a fix that replaces the .expect() call with proper error handling using a closure that returns a Result on failure [1][3]. Users should upgrade to v1.5.0 or later. No workaround is available, although the vulnerable code path is not triggered during normal operation [2].

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

1
8e8b0abdb1b6

Fix panic in RequestBatchSet

https://github.com/nimiq/core-rs-albatrossviquezclaudioApr 29, 2026via ghsa
3 files changed · +25 8
  • blockchain/src/chain_store.rs+3 0 modified
    @@ -333,6 +333,9 @@ impl ChainStore {
                         // find if there is a previous non-prunable macro block
                     }
                 }
    +            if prev_macro_block_number <= Policy::genesis_block_number() {
    +                break;
    +            }
                 prev_macro_block_number = Policy::macro_block_before(prev_macro_block_number);
             }
             Ok(blocks.into_iter().rev().collect())
    
  • consensus/src/messages/handlers.rs+20 8 modified
    @@ -128,6 +128,24 @@ impl<N: Network> Handle<N, Arc<RwLock<Blockchain>>> for RequestBatchSet {
                 Ok(Block::Micro(_)) => return Err(BatchSetError::MicroBlockGiven),
                 Err(_) => return Err(BatchSetError::TargetHashNotFound),
             };
    +
    +        let prove_history_len =
    +            |batch_set_hash: &Blake2bHash, block_number: u32| -> Result<_, BatchSetError> {
    +                blockchain
    +                    .history_store
    +                    .prove_num_leaves(block_number, None)
    +                    .map_err(|error| {
    +                        log::error!(
    +                            error = ?error,
    +                            requested_hash = %self.hash,
    +                            batch_set_hash = %batch_set_hash,
    +                            block_number,
    +                            "Failed to prove history size for batch set request"
    +                        );
    +                        BatchSetError::CouldntProduceHistorySizeProof
    +                    })
    +            };
    +
             // Try to get the epoch chunk hashes following the given macro block.
             // For each hash, fetch the macro block and its history length, and build a batch set.
             // If there are no chunks, create a single batch set with the provided block.
    @@ -144,10 +162,7 @@ impl<N: Network> Handle<N, Arc<RwLock<Blockchain>>> for RequestBatchSet {
                         .get_block(&macro_hash, true, None)
                         .expect("Macro block must exist since it can't be pruned");
     
    -                let history_len = blockchain
    -                    .history_store
    -                    .prove_num_leaves(macro_block.block_number(), None)
    -                    .expect("Failed to prove history size");
    +                let history_len = prove_history_len(&macro_hash, macro_block.block_number())?;
     
                     let batch_set = BatchSet {
                         macro_block: macro_block.unwrap_macro(),
    @@ -158,10 +173,7 @@ impl<N: Network> Handle<N, Arc<RwLock<Blockchain>>> for RequestBatchSet {
                 batch_sets
             } else {
                 // If there are no epoch chunks, create a single batch set from the given macro block.
    -            let history_len = blockchain
    -                .history_store
    -                .prove_num_leaves(block.block_number(), None)
    -                .expect("Failed to prove history size");
    +            let history_len = prove_history_len(&self.hash, block.block_number())?;
     
                 let batch_set = BatchSet {
                     macro_block: block.clone(),
    
  • consensus/src/messages/mod.rs+2 0 modified
    @@ -275,6 +275,8 @@ pub enum BatchSetError {
         TargetHashNotFound,
         #[error("the hash of a micro block was given")]
         MicroBlockGiven,
    +    #[error("couldn't produce history size proof")]
    +    CouldntProduceHistorySizeProof,
         #[error("unknown error")]
         #[serde(other)]
         Other,
    

Vulnerability mechanics

Root cause

"Missing bounds check in `get_epoch_chunks` allows iteration past the genesis block, causing `Policy::macro_block_before` to panic when the genesis block's hash is supplied via a `RequestBatchSet` message."

Attack vector

An unauthenticated remote attacker sends a `RequestBatchSet` message containing the genesis block's hash. The handler calls `get_epoch_chunks`, which iterates backwards through macro blocks using `Policy::macro_block_before`. When the iteration reaches the genesis block number, `macro_block_before` panics with "No macro blocks before genesis block", crashing the full node. No special privileges or network position is required beyond the ability to send a crafted message to the node.

Affected code

The vulnerability is in `blockchain/src/chain_store.rs` where `get_epoch_chunks` iterates backwards through macro blocks without checking for the genesis boundary, and in `consensus/src/messages/handlers.rs` where `prove_num_leaves` calls use `expect()` which panics on failure. The `consensus/src/messages/mod.rs` file defines the error types [patch_id=1262097].

What the fix does

The patch adds a guard in `chain_store.rs` that breaks the backward iteration loop when `prev_macro_block_number <= Policy::genesis_block_number()`, preventing the call to `Policy::macro_block_before` that would panic. Additionally, the patch replaces `expect("Failed to prove history size")` calls in `handlers.rs` with a fallible helper `prove_history_len` that returns a `BatchSetError::CouldntProduceHistorySizeProof` error instead of panicking. A new error variant `CouldntProduceHistorySizeProof` is added to `BatchSetError` to handle this case gracefully [patch_id=1262097].

Preconditions

  • networkAttacker must be able to send a RequestBatchSet message to the target node
  • inputAttacker must supply the genesis block's hash in the RequestBatchSet message

Generated on May 21, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.