High severity7.5NVD Advisory· Published Mar 31, 2026· Updated Apr 3, 2026
CVE-2026-34209
CVE-2026-34209
Description
mppx is a TypeScript interface for machine payments protocol. Prior to version 0.4.11, the tempo/session cooperative close handler validated the close voucher amount using "<" instead of "<=" against the on-chain settled amount. An attacker could submit a close voucher exactly equal to the settled amount, which would be accepted without committing any new funds, effectively closing or griefing the channel for free. This issue has been patched in version 0.4.11.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
mppxnpm | < 0.4.11 | 0.4.11 |
Affected products
1Patches
13 files changed · +41 −3
.changeset/close-voucher-settled.md+5 −0 added@@ -0,0 +1,5 @@ +--- +'mppx': patch +--- + +Fixed close voucher validation to reject vouchers equal to the on-chain settled amount.
src/tempo/server/Session.test.ts+29 −0 modified@@ -1143,6 +1143,35 @@ describe.runIf(isLocalnet)('session', () => { ).rejects.toThrow('close voucher amount must be >=') }) + test('rejects close equal to on-chain settled amount', async () => { + const { channelId, serializedTransaction } = await createSignedOpenTransaction(10000000n) + const server = createServer() + + // Open with 1M voucher (matches openServerChannel default) + await openServerChannel(server, channelId, serializedTransaction) + + // Settle on-chain so settled becomes 1000000 + const settleTxHash = await settle(store, client, channelId, { escrowContract }) + await waitForTransactionReceipt(client, { hash: settleTxHash }) + + // Try to close with voucher == on-chain settled — should be rejected + // because replaying the settled amount doesn't commit new funds + await expect( + server.verify({ + credential: { + challenge: makeChallenge({ id: 'challenge-2', channelId }), + payload: { + action: 'close' as const, + channelId, + cumulativeAmount: '1000000', + signature: await signTestVoucher(channelId, 1000000n), + }, + }, + request: makeRequest(), + }), + ).rejects.toThrow('close voucher amount must be >') + }) + test('rejects close exceeding on-chain deposit', async () => { const { channelId, serializedTransaction } = await createSignedOpenTransaction(10000000n) const server = createServer()
src/tempo/server/Session.ts+7 −3 modified@@ -815,10 +815,14 @@ async function handleClose( throw new ChannelClosedError({ reason: 'channel is finalized on-chain' }) } - const minCloseAmount = channel.spent > onChain.settled ? channel.spent : onChain.settled - if (voucher.cumulativeAmount < minCloseAmount) { + if (voucher.cumulativeAmount < channel.spent) { throw new VerificationFailedError({ - reason: `close voucher amount must be >= ${minCloseAmount} (max of spent and on-chain settled)`, + reason: `close voucher amount must be >= ${channel.spent} (spent)`, + }) + } + if (voucher.cumulativeAmount <= onChain.settled) { + throw new VerificationFailedError({ + reason: `close voucher amount must be > ${onChain.settled} (on-chain settled)`, }) }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/wevm/mppx/commit/94088246ee18f21b5d6be40d9e7a464f5a280bfbnvdPatchWEB
- github.com/wevm/mppx/security/advisories/GHSA-mv9j-8jvg-j8mrnvdPatchVendor AdvisoryWEB
- github.com/advisories/GHSA-mv9j-8jvg-j8mrghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-34209ghsaADVISORY
- github.com/wevm/mppx/releases/tag/mppx@0.4.11nvdRelease NotesWEB
News mentions
0No linked articles in our index yet.