Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-54541

CVE-2026-54541: Nimiq Rust Implementation DOS Vulnerability

CVE-2026-54541 is a denial of service flaw in Nimiq Rust implementation that allows malicious peers to crash syncing nodes. This post explains its technical details, affected versions, impact, and mitigation steps.

Published:

CVE-2026-54541 Overview

CVE-2026-54541 is a denial-of-service vulnerability in Nimiq core-rs-albatross, a Rust implementation of the Nimiq Proof-of-Stake protocol built on the Albatross consensus algorithm. Versions prior to 1.6.0 crash when a malicious state-sync peer sends a crafted TrieChunk proof containing two TrieProofNode values with identical keys. The panic occurs in TrieProofNode::child_index before cryptographic proof validation, so the attacker does not need a valid proof. The issue is fixed in version 1.6.0.

Critical Impact

A malicious state-sync peer can crash a syncing Nimiq node by delivering an unvalidated TrieChunk payload that triggers an unwrapped None in the trie proof code.

Affected Products

  • Nimiq core-rs-albatross versions prior to 1.6.0
  • Nimiq Proof-of-Stake nodes performing state sync
  • Downstream deployments consuming the nimiq-primitives trie module

Discovery Timeline

  • 2026-09-14 - CVE-2026-54541 published to the National Vulnerability Database (NVD)
  • 2026-09-16 - Last updated in the NVD database

Technical Details for CVE-2026-54541

Vulnerability Analysis

The defect is an Uncaught Exception ([CWE-248]) in the Merkle Radix trie proof verification path. During state sync, a peer delivers a ResponseChunk that flows through commit_chunks and put_chunk before reaching proof.verify. Inside TrieProof::verify, each proof node calls TrieProofNode::child_index in primitives/src/trie/trie_proof_node.rs. The check self.key.is_prefix_of(child_prefix) accepts equal keys, and KeyNibbles::get is then called at an offset equal to the key length. That call returns None, and the code unconditionally invokes unwrap(), panicking the process.

Because the panic occurs before cryptographic validation, the attacker never needs to forge a legitimate proof. The panic is transient: the node restarts and resynchronizes, but repeated targeting during peer selection prolongs availability loss for the victim.

Root Cause

The root cause is an incorrect precondition in TrieProofNode::child_index. The prefix check permits self.key and child_prefix to be equal, while the subsequent nibble lookup assumes child_prefix is strictly longer. When the two lengths match, KeyNibbles::get(self.key.len()) yields None and unwrap() triggers the panic.

Attack Vector

Exploitation requires the attacker to be selected as the victim's sync peer during state sync. Once selected, the attacker sends a TrieChunk whose proof contains two TrieProofNode values with identical keys. The victim reaches the vulnerable code path without any prior cryptographic gating, producing a process-level panic.

rust
// Security patch: primitives/src/trie/trie_proof_node.rs
// Reject equal-length keys in TrieProofNode::child_index
pub fn child_index(&self, child_prefix: &KeyNibbles) -> Result<usize, MerkleRadixTrieError> {
-    if !self.key.is_prefix_of(child_prefix) {
+    if !self.key.is_prefix_of(child_prefix) || self.key.len() == child_prefix.len() {
         error!(
-            "Child's prefix {} is not a prefix of the node with key {}!",
+            "Child's prefix {} is not a strict prefix of the node with key {}!",
             child_prefix, self.key,
         );
         return Err(MerkleRadixTrieError::WrongPrefix);
     }

-    // PITODO: return error instead of unwrapping
-    Ok(child_prefix.get(self.key.len()).unwrap())
+    child_prefix
+        .get(self.key.len())
+        .ok_or(MerkleRadixTrieError::WrongPrefix)
}

Source: Nimiq security patch commit 41d35ac

Detection Methods for CVE-2026-54541

Indicators of Compromise

  • Repeated Nimiq node crashes during the state-sync phase, followed by automatic restart and resync loops.
  • Log entries containing Child's prefix ... is not a prefix of the node with key ... from trie_proof_node.rs.
  • Panic backtraces referencing TrieProofNode::child_index, TrieProof::verify, put_chunk, or commit_chunks.

Detection Strategies

  • Monitor process exit codes and restart counters on validator and full-node hosts running core-rs-albatross.
  • Correlate crashes with the identity of the peer serving ResponseChunk messages immediately before the fault.
  • Track the deployed binary version and alert when nodes report a version earlier than 1.6.0.

Monitoring Recommendations

  • Ship node stdout/stderr and panic logs to a centralized log platform for pattern matching on trie proof errors.
  • Track sync-peer selection metrics and flag peers whose sessions consistently precede a panic.
  • Alert on sudden drops in chain height progression or elevated resync frequency across the fleet.

How to Mitigate CVE-2026-54541

Immediate Actions Required

  • Upgrade all Nimiq core-rs-albatross nodes to version 1.6.0 or later.
  • Restart running nodes after upgrading to ensure the patched TrieProofNode::child_index logic is loaded.
  • Review peering configuration to limit exposure to untrusted state-sync peers where operationally feasible.

Patch Information

The fix ships in Nimiq core-rs-albatrossv1.6.0. The change rejects equal-length keys in TrieProofNode::child_index and replaces the panicking unwrap() with an Err(MerkleRadixTrieError::WrongPrefix) return. See the GitHub Security Advisory GHSA-46wq-28cx-mhw4, Pull Request #3789, and the v1.6.0 release notes.

Workarounds

  • No supported configuration workaround exists; upgrading to 1.6.0 is the only remediation.
  • Operators may temporarily prefer trusted peers or restrict state-sync partners to reduce exposure until the upgrade completes.
  • Implement supervisor-level rate limiting on restart loops to preserve host stability during transient panics.
bash
# Upgrade example: pull and build the patched release from source
git clone https://github.com/nimiq/core-rs-albatross.git
cd core-rs-albatross
git checkout v1.6.0
cargo build --release

# Verify the running binary reports the patched version before resuming sync
./target/release/nimiq-client --version

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.