Apr 22, 2026·6 min read·5 visits
A critical flaw in core-rs-albatross prior to v1.3.0 permits integer truncation during multi-signature aggregation. Attackers with a single validator slot can use high-value indices that truncate to their valid slot, falsely inflating the signer count to bypass the consensus quorum.
An integer truncation vulnerability in the Nimiq Albatross Proof-of-Stake implementation allows a malicious validator to bypass the 2f+1 consensus quorum requirement. By crafting a BitSet with out-of-bounds indices that alias to the same 16-bit validator slot, an attacker can forge valid multi-signatures to finalize arbitrary blocks or manipulate chain liveness.
The Nimiq Albatross protocol utilizes a Proof-of-Stake consensus algorithm requiring a strict supermajority to finalize state transitions. The core-rs-albatross component manages this consensus logic, handling cryptographic proofs such as SkipBlockProof, TendermintProof, and DoubleVoteProof. These proofs rely on multi-signatures aggregated from a defined validator set.
To represent participating signers, the implementation uses a BitSet where each set bit corresponds to a validator's slot index. The protocol verifies that the number of participants meets the required quorum before cryptographic verification occurs. This structural separation between quorum validation and cryptographic aggregation exposes a critical attack surface.
CVE-2026-33471 represents an improper input validation and integer truncation flaw in this verification pipeline. The bug during the signer aggregation phase allows an attacker to desynchronize the internal state between the quorum counter and the public key aggregator. This flaw breaks the fundamental safety and liveness guarantees of the Nimiq consensus mechanism.
The vulnerability originates from an architectural disconnect between how the signer count is evaluated and how validator public keys are retrieved. When processing a proof, the software first evaluates self.sig.signers.len() to ensure the number of provided signatures meets the Policy::TWO_F_PLUS_ONE threshold. This check evaluates the raw number of elements in the BitSet.
The underlying BitSet implementation stores indices as usize values. On a standard 64-bit architecture, a usize can hold values up to $2^{64}-1$. However, the maximum number of legitimate validator slots is strictly bounded by a 16-bit integer limit, typically defined by the Policy::SLOTS constant.
During the public key aggregation phase, the application iterates over the BitSet indices to fetch corresponding validator keys. The vulnerable logic unconditionally casts the usize index to a u16 using the as u16 operator. This truncation effectively applies a modulo $65536$ operation to the index. Consequently, a usize index of $X$, $X + 65536$, and $X + 131072$ will all truncate to the exact same u16 value $X$.
An attacker populates the BitSet with multiple artificially large indices that alias to the same valid validator slot. The initial quorum check validates these entries as distinct signers, incrementing the participant count. The aggregation loop then truncates these indices, fetching and aggregating the identical public key multiple times.
The vulnerable implementation executes the quorum check and public key aggregation sequentially without bounds validation on the elements. The fold operation directly processes the unvalidated usize values from the BitSet.
// Vulnerable logic in core-rs-albatross
if self.sig.signers.len() < Policy::TWO_F_PLUS_ONE as usize {
return false; // Quorum validation passes based on unvalidated length
}
let agg_pk = self.sig.signers.iter().fold(AggregatePublicKey::new(), |mut aggregate, slot| {
// Unsafe cast from usize to u16 leads to integer truncation
let pk = validators.get_validator_by_slot_number(slot as u16).voting_key;
aggregate.aggregate(pk);
aggregate
});The mitigation introduced in commit d02059053181ed8ddad6b59a0adfd661ef5cd823 centralizes the validation logic into a new helper function named checked_signer_slots. This function enforces strict boundary checks before any type casting or aggregation occurs.
// Patched logic in core-rs-albatross v1.3.0
pub(crate) fn checked_signer_slots(signers: &BitSet) -> Option<Vec<u16>> {
let mut slots = Vec::with_capacity(signers.len());
for slot in signers.iter() {
// Enforce Policy::SLOTS limit and prevent u16 overflow
if slot >= Policy::SLOTS as usize || slot > u16::MAX as usize {
return None;
}
slots.push(slot as u16);
}
Some(slots)
}By returning an Option<Vec<u16>>, the protocol dictates that any proof containing out-of-bounds indices will fail verification entirely. The subsequent quorum check and aggregation logic are updated to consume this pre-validated vector, ensuring the validation count perfectly aligns with the parsed identities.
Exploitation requires the attacker to control at least one valid validator slot within the current consensus epoch. The attacker leverages this single slot to synthesize a multi-signature that falsely satisfies the network's supermajority requirement.
The attacker constructs a malicious BitSet containing their legitimate slot index $X$ alongside multiple aliased indices such as $X + 65536$ and $X + 131072$ up to the required quorum threshold. To the BitSet::len() function, this appears as a sufficient quantity of distinct signers. To the aggregation loop, this appears as multiple instances of the attacker's public key.
To produce a valid BLS multi-signature corresponding to this aggregated key, the attacker takes their valid individual signature and multiplies it by the number of aliases used. BLS signatures support linear aggregation, meaning $Sig(X) \times N$ perfectly authenticates against the aggregated public key $PK(X) \times N$. The verifier accepts the proof as a legitimate network supermajority.
The successful exploitation of this vulnerability results in a total compromise of the Nimiq Albatross consensus mechanism. An attacker with minimal actual network stake can assert unilateral control over network state transitions.
The primary consequence is the ability to finalize invalid blocks. By forging TendermintProof objects, the malicious validator can append arbitrary data to the blockchain ledger, execute double-spend attacks, or halt the processing of legitimate transactions entirely. The attacker bypasses the Byzantine Fault Tolerance guarantees that underpin the protocol's safety.
The attacker can also forge SkipBlockProof messages to manipulate the validator scheduling mechanism. This allows the adversary to force specific epochs or disrupt liveness by continuously advancing the chain without processing standard blocks. Equivocation proofs can similarly be bypassed, preventing the network from penalizing the attacker's malicious behavior.
The sole effective remediation for CVE-2026-33471 is upgrading all consensus nodes to core-rs-albatross version 1.3.0 or later. This upgrade modifies the cryptographic verification pipeline to reject malformed multi-signature bitsets natively.
Operators must coordinate the update across the network to prevent consensus forks. Nodes running the unpatched software will accept maliciously crafted blocks that patched nodes reject, causing network divergence. No backward-compatible configuration workaround exists because the vulnerability resides in fundamental message parsing and cryptographic aggregation algorithms.
Network defenders can deploy monitoring logic to retroactively identify exploitation attempts. Security systems should inspect serialized consensus messages and flag any BitSet indices exceeding the Policy::SLOTS threshold or the u16::MAX boundary. Detecting such indices provides a high-confidence indicator of active exploitation attempts against the validator network.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
core-rs-albatross Nimiq | < 1.3.0 | 1.3.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-190, CWE-20, CWE-1284 |
| Attack Vector | Network |
| CVSS v3.1 | 9.6 (Critical) |
| Impact | Consensus Bypass, Remote Code Execution (State Transition Logic) |
| Exploit Status | Proof of Concept Available |
| CISA KEV | Not Listed |
Integer Overflow or Wraparound (specifically truncation from usize to u16)