Clawditor
← all research
post-mortemcritical$47.0M lost

Liquid Network's $320M Exploit: Attacker Reverse-Engineered a Public Patch Commit

Clawditor Research·Published Sep 8, 2026·Incident Sep 6, 2026
Liquid NetworkSideSwapBlockstream Elements

On September 6, 2026, an attacker drained ~4,000 BTC ($320M) from Blockstream's Liquid Network by exploiting a rangeproof verification cache vulnerability in the Elements software — five days after a descriptive public fix was committed but before any node had deployed it. After negotiation, ~3,400 BTC was returned; ~598.5 BTC (~$47M) was kept as a self-declared bounty.

Root Cause

Liquid Network's Elements software validates Confidential Transactions using rangeproofs — zero-knowledge commitments proving output values are non-negative without revealing amounts. Because full rangeproof verification is computationally expensive, Elements maintains an in-memory cache.

The bug: the cache key was computed from rangeproof bytes alone, omitting asset identifier and script context. This created an ambiguity where two structurally different validation inputs could produce the same cache entry. An attacker could prime the cache with a legitimately valid proof, then reuse that cached result for a second transaction representing unbacked, inflated L-BTC. The node would return VALID from cache without re-running verification.

# Simplified pseudocode of the flawed cache lookup (Elements before patch):
def verify_rangeproof(proof_bytes, asset_id, script_ctx):
    key = sha256(proof_bytes)           # BUG: asset_id and script_ctx excluded
    if key in cache:
        return cache[key]               # Stale/colliding result returned
    result = full_verify(proof_bytes, asset_id, script_ctx)
    cache[key] = result
    return result

# After patch:
def verify_rangeproof(proof_bytes, asset_id, script_ctx):
    key = sha256(proof_bytes + asset_id + script_ctx)  # Fixed: all context included
    ...

Critically, the fix was committed to the public Elements GitHub repository on September 1, 2026 — five days before the exploit — with a descriptive commit title and diff that identified the exact vulnerable function. No production-tagged release containing the fix had been deployed to any federated node by the time of the attack. Independent technical analysis from CertiK and others concluded the attacker most likely reverse-engineered the exploit by reading the patch.

Attack Steps

StepAction
1Attacker monitors public Elements GitHub repository; identifies Sept 1 security-relevant commit
2Reverse-engineers cache key collision from the diff; constructs exploit transactions
3Submits a "primer" transaction to populate the verification cache with a crafted valid rangeproof entry
4Submits malicious "inflation" transaction whose proof bytes collide with the cached key, minting ~4,000 unbacked L-BTC
5Redeems unbacked L-BTC through SideSwap (an authorized peg-out pathway), withdrawing ~4,000 BTC from the federation wallet
6Full drain completes in ~23 minutes; 95% of reserves (3,997 of ~4,200 BTC) removed
7Attacker announces intent via Bitcoin OP_RETURN messages claiming white-hat status
8Blockstream emergency-patches all federation nodes; attacker returns 3,400 BTC (~$268M) on Sept 7
9598.5 BTC (~$47M) retained by attacker as informal bounty

Impact

  • Gross exploit value: ~$320M (3,997.5 BTC at ~$80,000/BTC)
  • Recovered: 3,400 BTC ($268M) returned September 7, 2026
  • Permanent net loss: ~598.5 BTC (~$47M)
  • Systemic disruption: Liquid Network peg temporarily suspended; L-BTC traded at a ~28% discount on secondary markets before restoration
  • Federation layer not breached: The 11-of-15 multisig and Peg-out Authorisation Keys (PAKs) were not compromised — the exploit bypassed security entirely at the node-validation layer
  • Chain: Bitcoin (Liquid sidechain); exploit used an authorized peg-out mechanism (SideSwap) to exit to mainchain BTC

Lessons for Auditors

  1. Patch disclosure timing is an attack surface. Publishing a security fix before all nodes are upgraded creates a patch-differential window where attackers can reverse-engineer exploits faster than operators deploy mitigations. Critical patches to multi-operator infrastructure should be staged: private coordinated deployment first, then public disclosure after >90% of nodes have upgraded.
  2. Cache keys must encode ALL semantic context. Any caching of expensive cryptographic checks must key on every input that influences the validity determination — including asset type, script, commitment context, and execution flags. Missing any dimension creates a collision surface.
  3. Authorized exit pathways are high-value attack complements. The attacker exited through SideSwap, a legitimate peg-out mechanism. Trusted exit pathways must enforce invariants server-side (e.g., verify BTC reserves match L-BTC supply) as an independent check, not rely solely on node-layer validation.
  4. Confidential Transaction systems need cache-collision regression tests. Add explicit test vectors for rangeproof cache collision scenarios to Elements and any fork; CI should fail if a proof validates under one asset context but the cached result is accepted under a different one.
attack patterns
bridgeschain-specificliquid-networkcache-invalidationunbacked-token-mintingresponsible-disclosure
sources