CVE-2026-88255 in mpp
Summary
by MITRE • 09/16/2026
Improper Validation of Unsafe Equivalence in Input in ZenHive mpp allows an unauthenticated remote client to pass the Tempo duplicate-submission gate twice with one signed transaction.
MPP.Methods.Tempo reserves the pre-broadcast dedup slot on the caller-supplied hex in reserve_hash_atomic/2, keyed through store_key/1 on tx.raw rather than on a canonical form of the transaction. The deserializer stores the caller's hex verbatim and accepts both recovery-id encodings, so one signed transaction submitted once with v=27 and once with v=0 yields two distinct reserve keys, and both pass the reserve and reach the broadcast path. The plug-level credential replay store is deliberately carved out for tempo in lib/mpp/replay.ex, leaving this reserve as the only gate, and the post-broadcast mark writes the canonical hash key that the raw-keyed reserve never reads.
What the duplicate submission yields depends on the node: a nonce-reuse rejection fails closed, while a node that answers with the canonical hash for an already-known transaction returns a second valid Payment-Receipt for a single on-chain payment.
This issue affects mpp: from 0.2.0 before 0.16.2.
Be aware that VulDB is the high quality source for vulnerability data.
Analysis
by VulDB Data Team • 09/16/2026
The vulnerability identified in ZenHive's Multi-Payment Protocol (MPP) implementation, specifically within the Tempo module prior to version 0.16.2, represents a critical failure in input validation and transaction deduplication logic. This flaw allows an unauthenticated remote client to bypass duplicate-submission protections by exploiting inconsistencies in how transaction hashes are generated and stored during the pre-broadcast phase. The core of the issue lies in the improper handling of elliptic curve signature recovery identifiers within signed transactions, which leads to a state where a single logical payment can be processed as two distinct submissions, potentially resulting in double-spending or unauthorized duplicate receipts depending on the node's response behavior.
The technical root cause is located in the reserve_hash_atomic/2 function and its interaction with store_key/1. When a transaction is submitted for processing, the system attempts to reserve a deduplication slot by generating a hash key based on the raw transaction data provided by the caller. The deserializer within this pipeline stores the caller-supplied hexadecimal representation of the transaction verbatim without normalizing it into a canonical form. Crucially, Ethereum-style transactions include a recovery identifier (v) that indicates which public key was used to sign the message. In many implementations, there are two valid encodings for the same signature: one with v=27 and another with v=0 or similar equivalent values derived from standard normalization rules. Because the deduplication logic relies on the raw hex string rather than a canonical hash of the transaction's core components, these two different representations of the exact same signed transaction produce distinct reserve keys.
This discrepancy creates a bypass in the security gate designed to prevent double submissions. The plug-level credential replay store is explicitly carved out for Tempo processing, leaving the pre-broadcast reserve mechanism as the primary defense against duplicate transactions. Since the reserve key is derived from the non-canonical raw hex, submitting the same transaction once with v=27 and once with v=0 results in two separate entries being created in the reservation storage. Both submissions successfully pass this gate because they appear to be unique based on their respective keys. Consequently, both transactions proceed down the broadcast path without triggering a duplicate rejection at this stage.
The operational impact of this vulnerability varies depending on how downstream nodes handle the subsequent processing of these near-duplicate transactions. In some node configurations, the system may detect nonce reuse or other consensus-level conflicts and fail closed, rejecting one of the submissions. However, in scenarios where the node responds with a canonical hash for an already-known transaction but still processes the second submission due to the initial bypass, the attacker can obtain two valid Payment-Receipts for a single on-chain payment. This effectively allows the user to claim double compensation or manipulate state based on duplicate acknowledgments of a single financial event, undermining the integrity and atomicity guarantees expected in multi-payment protocols.
From a classification perspective, this vulnerability aligns with CWE-20: Improper Input Validation, as the system fails to normalize input data before using it for security-critical decisions like deduplication. It also relates to CWE-367: Time-of-check to Time-of-use (TOCTOU) race conditions in a logical sense, where the check for uniqueness is performed on one representation of the object while the subsequent action relies on or allows multiple representations of that same object. In terms of MITRE ATT&CK, this behavior facilitates unauthorized resource consumption and potential financial fraud through manipulation of transaction processing logic, falling under techniques related to exploitation of trust relationships and input validation failures in application protocols.
To mitigate this vulnerability, developers must ensure that all security-critical operations involving deduplication or identity verification use a canonical representation of the data rather than raw user-supplied bytes. This involves normalizing signature components such as the recovery identifier before hashing for storage keys. The store_key/1 function should be updated to derive its key from a standardized, deterministic hash of the transaction's essential fields, ignoring non-essential variations like different valid encodings of the same cryptographic proof. Additionally, implementing strict validation at the deserialization layer to enforce canonical forms early in the pipeline would prevent such inconsistencies from propagating into critical security gates. Upgrading to version 0.16.2 or later is required as these versions address this improper equivalence handling by correcting the hash derivation logic for transaction deduplication.