Clawditor
← all research
post-mortemmedium$191K lost

Allbridge: $191K Drained via Forged CCTP Message — Circle Attested What It Never Verified

Clawditor Research·Published Aug 11, 2026·Incident Aug 19, 2026
Allbridge

In a month-long attack, an adversary exploited Allbridge's Base CCTP router by constructing a forged cross-chain message that Circle attested without verifying an actual USDC burn occurred. Missing sender, origin, and amount validation in `receiveCctpMessage` let the attacker claim a phantom $1M credit and drain 191,156 USDC with an Aave flash loan.

Root Cause

Allbridge's CCTP (Cross-Chain Transfer Protocol) integration on Base accepted Circle attestations as proof that a legitimate USDC transfer had occurred. However, Circle's MessageTransmitter only validates the cryptographic signature of a message — it does not verify that an equivalent USDC burn happened on the source chain, who initiated the message, or whether the claimed amount matches an on-chain mint.

Allbridge's receiveCctpMessage function failed to independently validate any of these three economic properties:

// Vulnerable Allbridge CCTPTokenMessenger (simplified)
function receiveCctpMessage(
    bytes calldata message,
    bytes calldata attestation
) external {
    // ❌ No check: msg.sender == Circle's canonical TokenMessenger
    // ❌ No check: the declared amount matches an actual on-chain USDC mint
    // ❌ No check: source domain + sender == expected burn address

    // Circle's transmitter only validates that Circle signed the message:
    bool success = IMessageTransmitter(transmitter)
        .receiveMessage(message, attestation);
    require(success, "CCTP receive failed");

    // amount is attacker-controlled within the forged message
    uint256 amount = _decodeAmount(message); // reads 1,000,000 USDC
    _creditRouter(amount);                    // ← credits phantom $1M
}

The critical insight: MessageTransmitter.sendMessage on Polygon can be called directly by anyone. Circle will issue a valid attestation for any well-formed message that doesn't reference a TokenMessenger burn — because Circle's role is message relay, not economic verification.

Attack Steps

#DateActionDetail
1Jul 26Forge CCTP messageAttacker calls MessageTransmitterV2.sendMessage directly on Polygon with src=Polygon, dst=Base, declared amount=1,000,000 USDC — no USDC burned
2Jul 26Obtain Circle attestationCircle issues valid attestation (it validates message format + signature, not economic reality)
3Jul 26–Aug 18WaitAttacker waits for Allbridge Base Router balance to accumulate enough legitimate USDC deposits
4Aug 19Balance threshold reachedBase Router balance reaches ~191,156 USDC
5Aug 19 (T+6 s)Submit forged messageCalls Allbridge receiveCctpMessage with forged message + Circle attestation; protocol credits phantom $1M
6Aug 19Flash loan + drainAave flash loan covers the difference between $1M phantom credit and actual balance; full 191,156 USDC drained

Impact

  • Loss: 191,156 USDC (~$191,156)
  • Chain: Base (bridge from Polygon)
  • Preparation window: ~24 days (July 26 → August 19)
  • Protocol response: Allbridge urged all liquidity providers to withdraw; router suspended
  • Root cause disclosure: SlowMist published a detailed post-mortem (Medium, August 2026)

Lessons for Auditors

  1. Circle attestation ≠ proof of USDC transfer. The CCTP attestation guarantees message authenticity, not economic validity. Bridge implementations must independently verify that: (a) the message was initiated by TokenMessenger (not MessageTransmitter directly), (b) a USDC burn of the declared amount occurred on the source chain, and (c) the destinationCaller matches expectations.
  2. Validate message sender identity at the receiver. Check that message.sender == TokenMessenger on the source chain, not just that Circle signed the outer envelope.
  3. Cross-chain bridge state must account for timing attacks. The attacker waited 24 days for the router balance to reach exploitable levels. Bridges should cap per-message withdrawal amounts relative to verified inflows, not total balance.
  4. Flash loan composability amplifies bridge exploits. Even a small phantom credit becomes dangerous when combined with flash loans. Bridges should use reentrancy guards and balance-checks that are flash-loan-aware.
  5. Consider allowlisting valid CCTP message initiators at the application layer — only messages that provably originated from the canonical USDC TokenMessenger (which enforces burns) should be credited.
attack patterns
bridgessignaturesflashloanserc20cctpcross-chain
sources