Litecoin MWEB Security Incident Postmortem

Litecoin MWEB Security Incident Postmortem

Summary

In March 2026, Litecoin developers identified a critical validation bug in Litecoin’s Mimblewimble Extension Block implementation. The bug allowed a block producer to construct a mined block containing an MWEB input whose supplied metadata did not match the actual MWEB UTXO being spent. Because this metadata was not fully revalidated during block connection, a malicious block could make a small MWEB input appear to support a much larger pegout.

A chain scan showed that the vulnerability had already been exploited once. At block height 3,073,882, an attacker used a malicious MWEB input to peg out 85,034.47285734 LTC. Developers moved quickly to coordinate an emergency miner-only rollout, prevent further exploitation, freeze the three resulting transparent outpoints, and contact the actor. The actor later cooperated by signing a recovery transaction that returned the funds except for an agreed 850 LTC bounty. Charlie purchased 850 LTC to cover the bounty, which was added to the recovered amount. That total amount was then pegged back into MWEB and the resulting MWEB output was frozen to restore the MWEB balance.

In April 2026, a second attacker or tester attempted to use the same original exploit path. This time, upgraded nodes rejected the bad block, but the way mutated MWEB blocks were handled caused certain RPC commands to hang, including those used by miners to submit mined blocks. This meant upgraded mining nodes became stuck or unable to continue normal mining operations. Unupgraded miners continued extending the bad chain, resulting in a 13-block invalid chain that was later reorged out after upgraded miners coordinated on the valid chain. This April incident affected some third-party services, including THORChain and NEAR/SwapKit-related infrastructure. Exact third-party transaction IDs and final loss amounts are still being collected.

The root bug has been fixed. Additional fixes were released to handle the historical exploit, recover and rebalance funds, harden amount accounting, and prevent mutated MWEB block data from blocking future valid block submission.

Scope

This postmortem covers two related incidents:

  1. March 2026 MWEB inflation exploit and recovery

    • A malicious MWEB input was accepted during block connection.
    • The attacker created an inflated pegout of 85,034.47285734 LTC.
    • The funds were quarantined, recovered through actor cooperation, and rebalanced into MWEB.
  2. April 2026 exploit-triggered DoS/reorg incident

    • A later attempt to use the same exploit path caused upgraded mining nodes to reject or get stuck on mutated MWEB block data.
    • Unupgraded miners continued mining an invalid chain.
    • The valid chain later overtook and reorged out 13 bad blocks.
    • Litecoin Core 0.21.5.4 addressed this failure mode.

This postmortem does not cover unrelated later MWEB findings or future hardening work except where they directly affected the response to these two incidents.

Impact

March incident

The March exploit created an MWEB accounting imbalance and produced an inflated transparent pegout of:

85,034.47285734 LTC

The exploit block was:

  • Height: 3,073,882
  • Hash: d1695b5d115f86927a9763768218118ba88b315844e1a0681fa08f6f008be622

The inflated pegout was initially sent to:

ltc1qacryk5tvwd3r3ru2zvakk5hy7ay08tf329n2nf

The attacker then split the funds into three transparent-chain outpoints, which were temporarily frozen by miner-enforced consensus rules:

Outpoint Address
9e3fa709f482d81442c8cd95ee45a34f603e60ea35795228ce948cdc60e0661f:0 ltc1qenrty3l47jejd09cdy8lhavhw5xvwr6xaxg59r
6708daa4c905adcfe3f0e4e498bd56dcd4e377cccd3948b15e1eb3f0f8ff4eca:0 ltc1qfrhkj3tfy0dnlka7cnzdke8xc7w852w94hn8de
861d2777f93e6998b576d97298ef0d0518b53a944619f897fd0f0b92ed4ea4b5:1 ltc1q0459q38cghmxpzw9pq2vqx96dpu88d5w40gjv3

The attacker attempted to spend at least one frozen output in transaction:

d21d580e5936cecc2c3cd28ea186bb354f324417d43f8ae2edf6a94e2a41df17

That transaction was rejected by upgraded miners.

The actor later signed a recovery transaction:

509e1c1a1198f27a3c8a3edc2f0bf99a6f8c89854112b64e98a487940a579258

That transaction paid:

  • 84,184.47278630 LTC total to the recovery address ltc1qqx0ar6pk70g784dh6uhxh6ndxpfczjayj6td2p, split across two outputs.
  • 850.00000000 LTC to an address controlled by the actor as the agreed bounty.
  • Approximately 0.00007104 LTC in transaction fee.

After recovery, the rebalancing peg-in transaction was:

435d889bd4f43a76d5a0b60b6d539b2b5e0dc5be5090a2ff8839f87d1cd6da6d

It pegged 85,034.47285734 LTC back into MWEB in block:

  • Height: 3,078,098
  • Hash: ad03808c1ed721a8994028b544abb74125e441a1fc42baa927b24c1c2f62ba56

The resulting MWEB output was frozen:

2f3a08d9f5ef5f388386c11efe935394b14b524220cff4ec5c81942b82e694f7

Because that was the only MWEB output in the block, it corresponds to the full rebalancing amount.

No confirmed user funds were ultimately lost in the March incident. The network did, however, temporarily rely on emergency miner coordination to prevent movement of the inflated outputs and to process the recovery transaction.

April incident

The April incident began with a bad block at:

  • Height: 3,095,931
  • Hash: 579ae05733b2ce28843a75ca39e6d5c6b5e95e7366f927381871fd34e36fb088

The invalid chain continued through:

  • Height: 3,095,943
  • Hash: f2e9d92d8cda4c0ae69cd0876965c084e46ef99ba9d8597a4b62a8227c504941

There were 13 bad blocks in total:

3095931: 579ae05733b2ce28843a75ca39e6d5c6b5e95e7366f927381871fd34e36fb088
3095932: 7d2b1a71237afb9014402a8ca92b202611b9c22499fead9a066a145f899d49be
3095933: 676ebdde8490b70db323224b37a185e497ba1c3c0666ffec7bc799f2bcac4e17
3095934: 52a268e68fc0d7599c48d0e7ab6863036d1e33520cbf70c54b3d1a16c51c9182
3095935: ebc061638e97c0a4e879a69c4f8fcb421feb248905ed739bb6f64dfba7820d8c
3095936: 01b4b389969117bba8c12f59d82294699b25ff8e1a4d230dbe5ee8077ffbaf24
3095937: f85d7390fe91c6770b77e689b2462e4c0316d844d790c4ad6116e7b2ad1d7171
3095938: 90b816b803c1d0923732e29108f19a87cc0d9a4fa458b4149bf7b72432f4f1be
3095939: 3b2ce00306b39aae12b929d07bc79d3ccea54fb1ed3039c71580712fa923662c
3095940: 5e3192692e48bcf6dfe135954c739c121c85ffdbf7335a4fc152238534fa4be9
3095941: 6a131f0ad38b16d68a1dbc110d18c6490c9e9de60dfb116dce09b3e04c9df2c2
3095942: 5bb03f68b4995879def2759660f996d2786425e3676112586c94f39a62740157
3095943: f2e9d92d8cda4c0ae69cd0876965c084e46ef99ba9d8597a4b62a8227c504941

The attacker’s invalid-chain pegouts were:

Block Amount Address
3,095,934 36,835.42 LTC ltc1qmf0sw2tpcmk4lx2n4eq4pgpjly8pvphnturfu4
3,095,936 41,126.87704000 LTC ltc1qtpgfflztghclrk00nuefvcerqq7juz45r0djqa
3,095,943 86,129.54 LTC ltc1qmf0sw2tpcmk4lx2n4eq4pgpjly8pvphnturfu4

Those blocks were reorged out. However, multiple third-party flows appear to have processed before the reorg completed.

External impact that we know of so far:

  • NEAR Intents: The attacker was able to swap 11000 LTC for 7.78814476 BTC through NEAR Intents. Those 11000 LTC were also no longer on the valid chain, resulting in a large loss for NEAR Intents. Explorer - NEAR Intents
    • Other attempts were made to swap additional litecoin, but those swaps were prevented in time. Ex: Explorer - NEAR Intents
  • THORChain: The attacker managed to swap 10 LTC for 0.00719957 BTC. After the reorg, those 10 LTC were no longer on the valid chain, resulting in a loss for THORChain. THORChain Network Explorer

Technical root cause

March: missing MWEB input metadata revalidation during block connection

MWEB inputs reference previous MWEB outputs. Those inputs also carry metadata used by the MWEB balance and spend validation logic, including the output commitment and receiver public key.

The intended rule is simple: when an MWEB input spends a previous output, the metadata supplied by the input must match the actual MWEB UTXO identified by the input’s output ID.

That check existed in some paths, including normal mempool and block construction paths. But it was not fully enforced in the block connection path. This meant a transaction created and mined by an attacker could bypass the normal paths and rely on the block connection logic accepting mismatched input metadata.

The malicious March input was:

  • MWEB input ID: 03af9dcadd42c8e0991edaa30237f3063c31243f48105454f5bcae9b4e9c9599
  • Actual value: unknown, but not more than 1.2084693 LTC
  • Actual UTXO commitment: 082be7968c953dc2dc29d903e784f732af269be85e50561e65e0d27c46ad0d747a
  • Fake commitment used for inflation: 0893b3f065cdbd7c670f3b5b3a9c75cab0235a926fc31d835480a2cd000551b2a7

The malicious kernel was:

  • Kernel ID: 089afa149f1e514ff7a307dc40c259228f2ad9f3e9bfbfddad62bb4018d8bdd43b
  • Pegout amount: 85,034.47285734 LTC
  • Pegout address: ltc1qacryk5tvwd3r3ru2zvakk5hy7ay08tf329n2nf

Because the attacker needed to bypass mempool and normal block-building validation, exploitation required mining a block or controlling a miner that would include the malformed MWEB data.

April: mutated MWEB block handling caused upgraded mining nodes to stall

The March fix made the original malformed MWEB input invalid for new blocks. However, MWEB block data has a subtle property: some serialized MWEB body data can be mutated without changing the canonical Litecoin block hash.

When an upgraded node received a mutated MWEB block over P2P, it could fail while applying the MWEB body and classify the failure as BLOCK_MUTATED. The node could then retain the bad serialized block data for that block hash. Since the same block hash might later arrive with valid non-committed data, retaining the mutated bytes could block later valid block processing or interfere with mining RPC flows such as submitblock.

During the April incident, this caused upgraded mining nodes to reject the bad block but also become unable to continue normal mining operations quickly enough. Unupgraded miners, which did not enforce the MWEB fix, continued extending the invalid chain until upgraded miners coordinated and overtook it.

Litecoin Core 0.21.5.4 fixed this by erasing stored block data for mutated blocks so that later valid data for the same block hash could be accepted and processed. The release also added a functional test demonstrating that a mutated P2P MWEB block does not prevent later valid block submission through mining RPC.

Response timeline

Dates are listed by incident phase. Exact wall-clock times can be added later if desired.

March 2026

March 19 — Vulnerability identified and chain scan confirms exploitation

Developers identified a plausible MWEB validation flaw during internal review. A chain scan showed the flaw had already been exploited recently at block 3,073,882, producing an inflated pegout of 85,034.47285734 LTC.

The team identified the malicious input, kernel, pegout, and resulting transparent outputs. The three transparent outpoints holding the inflated funds were still unspent.

March 19–20 — Emergency miner coordination and 0.21.5 / 0.21.5.1 rollout

Developers coordinated privately with major mining pools. The initial goal was to prevent any further exploit blocks while avoiding a public disclosure that would alert the actor before the inflated outputs were contained.

The first emergency release, 0.21.5, added validation to prevent new malformed MWEB inputs. Because it did not yet include a historical exception for the already-accepted exploit block, miners were instructed not to reindex or resync on that version.

A follow-up miner-only release, 0.21.5.1, added a one-block historical exception for the known exploit block and temporarily rejected spends of the three attacker-controlled transparent outpoints.

March 20–24 — Attempted spend blocked, recovery plan prepared

The actor attempted to spend at least one frozen output. Upgraded miners rejected the attempted spend.

The team then contacted the actor. The actor agreed to cooperate by signing a recovery transaction that returned the funds except for an 850 LTC bounty. Developers prepared 0.21.5.2, which allowed one specific recovery transaction to spend the frozen transparent outputs while continuing to reject any other spend of those outputs.

March 24 — 0.21.5.2 rollout and recovery transaction mined

After coordinating with mining pools, developers released 0.21.5.2 to miners and waited for sufficient upgrade coverage before broadcasting the recovery transaction.

The recovery transaction was:

509e1c1a1198f27a3c8a3edc2f0bf99a6f8c89854112b64e98a487940a579258

It returned the recovered funds to a developer-controlled recovery address and paid the agreed 850 LTC bounty to the actor.

March 25 — Rebalancing peg-in mined

The recovered amount was pegged back into MWEB using transaction:

435d889bd4f43a76d5a0b60b6d539b2b5e0dc5be5090a2ff8839f87d1cd6da6d

This peg-in was mined at block height 3,078,098. The block contained only one MWEB output, allowing the team to identify the rebalancing output precisely:

2f3a08d9f5ef5f388386c11efe935394b14b524220cff4ec5c81942b82e694f7

That MWEB output was frozen in the later permanent fix so that MWEB accounting was rebalanced while the returned coins could not be spent again.

March 26 — Permanent fix and hardening prepared

Developers began preparing 0.21.5.3, which replaced the temporary transparent-output freeze and special recovery transaction handling with the permanent MWEB rebalance freeze. It also included additional MWEB amount-accounting hardening, including safe handling of kernel fee and supply-change arithmetic.

April 2026

April 25 — New exploit attempt and invalid-chain growth

A later actor attempted to use the same original MWEB exploit path beginning at block height 3,095,931. Upgraded nodes rejected the bad MWEB data, but the rejection path exposed the mutated-block handling issue. Several upgraded mining nodes were unable to continue mining normally, while unupgraded miners continued extending the invalid chain.

The invalid chain grew to height 3,095,943, for a total of 13 bad blocks.

April 25 — Coordinated valid-chain recovery

Mining pools coordinated to invalidate the bad block, share valid-chain blocks, and extend the valid chain until it overtook the invalid chain. The network successfully reorged out the 13-block invalid chain.

The invalid-chain pegouts were removed by the reorg. However, some third-party systems had observed or processed activity on the invalid chain before the reorg completed.

April 25 — 0.21.5.4 prepared and released

Developers prepared 0.21.5.4 as a minimal public fix for the mutated-block DoS/reorg failure mode. The key behavioral change was to erase stored block data for blocks classified as mutated so that valid block data for the same block hash could later be accepted. A new functional test covered the case where a mutated P2P MWEB block should not prevent later submitblock mining.

0.21.5.4 was built and released publicly on April 25. Pools and services were instructed to upgrade.

Release map

Version Purpose
0.21.5 Initial emergency miner-only fix to reject new malformed MWEB input metadata. Unsafe for reindex/resync because it would reject the already-accepted historical exploit block.
0.21.5.1 Miner-only emergency fix with a historical exception for the known exploit block and a temporary freeze on the three transparent outpoints containing the inflated pegout.
0.21.5.2 Miner-only recovery release allowing one approved transaction to spend the frozen transparent outpoints and return the funds, while continuing to reject other spends.
0.21.5.3 Permanent MWEB repair release: replaced the temporary transparent-output quarantine with a frozen MWEB rebalancing output, retained the historical exception, and added additional MWEB amount-accounting hardening.
0.21.5.4 Public fix for the April mutated-block DoS/reorg failure mode; erased retained mutated block data and added regression coverage for mutated MWEB blocks interfering with later valid block submission.

Why the March recovery used a frozen MWEB output

The exploit created transparent LTC through an invalid MWEB pegout. Once the actor returned the funds, simply holding or burning transparent LTC was not enough to make MWEB accounting internally consistent.

The recovery process therefore did two things:

  1. Returned the inflated transparent LTC to developer control.
  2. Pegged the same amount back into MWEB and froze the resulting MWEB output.

This restored the relationship between MWEB’s internal supply accounting and the transparent-chain value backing MWEB, while preventing the rebalancing output from being spent. In effect, the network carried forward the historical exploit block but neutralized its economic effect.

Why the April event caused a reorg

The March fix prevented upgraded miners from accepting the malformed MWEB input. But the April attacker’s block also triggered the mutated-block handling problem. Most upgraded mining nodes could not quickly recover and continue mining valid blocks. Meanwhile, unupgraded miners still accepted and extended the invalid chain.

Once upgraded miners coordinated, shared valid blocks, and extended the valid chain, the valid chain overtook the invalid one. Nodes following correct validation rules then reorged out the bad chain.

The April reorg was therefore not a rollback of valid Litecoin history. It was a reorg of an invalid chain produced by miners that had not upgraded or had not fully enforced the MWEB validation rules.

What went well

The original vulnerability was identified internally before public disclosure, and the chain scan quickly showed that exploitation had occurred only once in March.

The inflated March outputs were still intact when discovered. This allowed developers and miners to contain the funds before they were dispersed.

Mining pools responded quickly to emergency coordination. The initial containment depended on miner cooperation, and enough hashrate upgraded in time to prevent additional confirmed movement of the inflated outputs.

The actor cooperated after contact. The signed recovery transaction avoided a more disruptive recovery path.

The rebalancing peg-in was mined in a block with only one MWEB output, which made the final frozen MWEB output cleanly identifiable.

During the April incident, upgraded miners coordinated quickly enough to overtake the invalid chain and reorg out the bad blocks.

What went wrong

MWEB validation relied too heavily on assumptions that were true in mempool and block-building paths but not fully enforced during block connection. Consensus-critical validation must be performed at block connection even if another path already checked it.

The initial emergency fix required careful miner-only deployment and explicit instructions not to reindex. That increased operational risk and made the response harder to explain.

The recovery required multiple staged miner releases. Each stage carried its own coordination risk.

The April issue showed that the mutated-block failure mode had not been sufficiently tested against mining RPC and block-submission behavior. Existing tests covered validation but did not fully cover how mutated MWEB block data interacted with later valid block submission.

The network response relied on ad hoc miner coordination. It worked, but it exposed the need for better maintained emergency contact paths, fork monitoring, and status dashboards.

Some ecosystem services were not prepared for a deep Litecoin reorg involving invalid-chain activity. Custom indexers and swap infrastructure may have processed stale or invalid-chain data differently from Litecoin Core nodes.

Q&A

Has the MWEB balance been fully restored?

Yes. The inflated pegout created an imbalance between MWEB and the transparent chain. After the actor returned the funds minus the agreed bounty, Charlie purchased the additional 850 LTC needed to make the amount whole. The full 85,034.47285734 LTC was then pegged back into MWEB in a single transaction. The resulting MWEB output was frozen, which restored the MWEB balance while ensuring those funds cannot be spent again.

Why did it take so long to finish Litecoin Core v0.21.5.3?

Once nearly all major mining pools had upgraded, we believed the network was protected against further exploitation of the original issue. At that point, the immediate emergency had passed, but we also knew that once the release was made public, many more people would be looking closely at the Litecoin codebase and the MWEB changes.

Before inviting that attention, we wanted to take extra time to review the relevant code paths and scan for related issues. We used the latest AI-assisted code review tools alongside manual review, and that process did find additional problems worth fixing before a public release, including MWEB fee and amount-accounting edge cases.

When the code itself was ready, the release process was then delayed by operational issues unrelated to the fix: expired certificates and loss of access to an Apple developer account delayed final signing and packaging of the release by about a week.

What should users do?

Users should upgrade to Litecoin Core v0.21.5.4 or later and verify that their node is syncing normally.

After upgrading, check that your node continues advancing and is not stuck on an old block. You can do this by comparing the block height shown by your node with a trusted block explorer or another known-good Litecoin node.

If your node is stuck and does not continue syncing after restarting Litecoin Core, you may need to reindex. At a high level:

  1. Shut down Litecoin Core cleanly.
  2. Start Litecoin Core once with the -reindex option.
  3. Let it fully rebuild and sync. This can take a while depending on your hardware.
  4. After it finishes, restart normally without -reindex.

Node operators, miners, exchanges, and services should also make sure they are not running one of the temporary miner-only emergency builds. The recommended public release is v0.21.5.4 or later.

A message from NEAR Intents to the attacker:

1 Like

Good news is that you guys were attentive.

2 Likes