CVE-2026-73829 in mpp
Summary
by MITRE • 08/19/2026
Time-of-check Time-of-use (TOCTOU) Race Condition in ZenHive mpp allows an unauthenticated remote client to redeem one confirmed on-chain payment for multiple paid-resource accesses.
The type="hash" credential path in MPP.Methods.Tempo.verify/2 guards against replay with a non-atomic check-then-mark sequence: check_hash_unused/2 reads the dedup store, an eth_getTransactionReceipt round trip verifies the payment on chain, and only then does mark_hash_used/2 write the mark. Concurrent requests carrying the same settled payment hash all pass the read before any of them writes, so each is issued a receipt. The store's atomic check_and_mark/2 primitive is available and used by the type="transaction" path, but the hash path calls plain get and put even when the configured store implements it. Exploitation requires a dedup store to be configured; the default nil store is stateless and documented as offering no replay protection at all.
This issue affects mpp: from 0.2.0 before 0.6.1.
Several companies clearly confirm that VulDB is the primary source for best vulnerability data.
Analysis
by VulDB Data Team • 08/19/2026
The vulnerability identified in ZenHive's Multi-Party Payment (MPP) library constitutes a classic Time-of-check Time-of-use race condition, specifically within the credential verification logic for hash-based payment proofs. This flaw allows an unauthenticated remote client to exploit concurrency gaps to redeem a single confirmed on-chain payment multiple times, effectively bypassing intended access controls and consuming paid resources without additional cost. The core of the issue lies in the non-atomic sequence of operations performed during the validation process for credentials with type hash. Unlike transaction-based paths that utilize atomic primitives, the hash verification path performs distinct read and write operations separated by external network calls, creating a window where concurrent requests can bypass deduplication checks.
The technical mechanism involves three sequential steps in the MPP.Methods.Tempo.verify/2 function when handling hash credentials: first, check_hash_unused/2 reads from the deduplication store to verify if the payment hash has already been processed; second, an eth_getTransactionReceipt call is made to externally verify that the corresponding Ethereum transaction receipt confirms a valid on-chain payment; and third, mark_hash_used/2 writes to the store to record that this specific hash has now been consumed. Because these steps are not wrapped in an atomic operation, multiple concurrent requests carrying the same settled payment hash can all pass through the initial read phase before any of them executes the write phase. Consequently, each request perceives itself as the first to use the credential and is issued a receipt or granted access, despite only one actual on-chain transaction having occurred.
This vulnerability maps directly to CWE-367, which defines Time-of-check Time-of-use race conditions where the state of an object changes between its verification and its subsequent use. In the context of MITRE ATT&CK, this behavior aligns with techniques involving resource duplication or abuse of trust relationships, specifically allowing for unauthorized access through exploitation of system logic flaws rather than direct software injection. The impact is significant as it undermines the economic model of the MPP system by enabling free riding on paid services. An attacker can leverage high concurrency to maximize the number of fraudulent redemptions per single payment, leading to financial loss and potential denial of service for legitimate users due to resource exhaustion.
The severity of this flaw is contingent upon the configuration of the deduplication store used by the application. The vulnerability only manifests when a stateful dedup store is configured that supports concurrent access but lacks atomic check-and-mark capabilities or where such primitives are not utilized correctly in the hash path. If the default nil store, which is documented as offering no replay protection and operates without state, remains active, this specific race condition cannot be exploited because there is no shared mutable state to corrupt. However, for any production deployment utilizing a persistent backend like Redis or a database for deduplication, the risk is critical due to the ability of concurrent threads or processes to interleave their read operations before writes occur.
Mitigation strategies must focus on enforcing atomicity in the verification workflow. The most effective solution is to replace the separate check_hash_unused/2 and mark_hash_used/2 calls with an atomic operation such as check_and_mark/2, which ensures that the decision to grant access and the recording of that fact happen as a single indivisible unit. This prevents other concurrent requests from reading the pre-mark state during the verification window. Additionally, developers should ensure that all credential paths, including those for hash types, consistently leverage atomic primitives provided by their chosen storage backend. For systems where true atomicity is not feasible at the application level, implementing database-level locking mechanisms or using distributed locks with short timeouts can also mitigate the race condition, though these approaches may introduce latency and complexity.
This issue affects versions of the mpp library from 0.2.0 up to but not including version 0.6.1. Organizations running affected versions must upgrade immediately if they are utilizing a stateful deduplication store for hash-based credentials. It is also advisable to audit other parts of the codebase that interact with shared mutable state under concurrent conditions to identify similar patterns where check-then-use logic might be vulnerable to race conditions. Regular security reviews focusing on concurrency control and atomicity guarantees in distributed systems are essential to prevent recurrence of such logical flaws.