CVE-2026-88255 PUBLISHED

mpp Tempo keys its pre-broadcast dedup reserve on the caller-supplied transaction encoding, so a re-encoded signed transaction reserves a second slot

Assigner: EEF
Reserved: 11.09.2026 Published: 16.09.2026 Updated: 16.09.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.

Metrics

CVSS Vector: CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
CVSS Score: 6.3

Product Status

Vendor ZenHive
Product mpp
Versions Default: unaffected
  • affected from 0.2.0 to 0.16.2 (excl.)
Vendor ZenHive
Product mpp
Versions Default: unaffected
  • affected from f8904666061fbab695874856d8fcd02c471dfe1b to e12bd4a1cea2e97c2a01fc059c48e5594a7b4a43 (excl.)

Affected Configurations

Reachable when MPP.Methods.Tempo broadcasts a type="transaction" credential with a dedup store in place. From mpp 0.7.0 the dedup store is on by default (the app-started MPP.Tempo.ConCacheStore; opt out with store: false), so every default Tempo deployment from 0.7.0 before 0.16.2 is affected. Before 0.7.0 the default store was nil, which runs the library statelessly and provides no application-level replay protection at all, a documented property rather than part of this issue; those versions are affected only where a "store" was configured explicitly in method_config.

Credits

  • E.FU finder
  • E.FU remediation developer
  • Jonatan Männchen / EEF coordinator

References

Problem Types

  • CWE-1289 Improper Validation of Unsafe Equivalence in Input CWE

Impacts

  • A client re-encodes the recovery id of a transaction it has already submitted and presents it again. The duplicate passes the only duplicate-submission gate the Tempo method has, and against a node that answers with the canonical hash for an already-known transaction the client is issued a second Payment-Receipt for one on-chain payment.