Back to Blog

Cross-Chain Bridge Security: Why Bridges Keep Getting Hacked

|Odin Scan Team
Cross-Chain Bridge Security: Why Bridges Keep Getting Hacked

Cross-chain bridges hold more value than most protocols and have a larger attack surface than any of them. Since 2021, bridge exploits have accounted for over $2.5 billion in losses. Ronin ($625M), Wormhole ($325M), Nomad ($190M), BNB Bridge ($570M), Multichain ($130M). The list keeps growing.

Bridges are hard to secure because they sit at the intersection of multiple trust domains. A bridge connects two (or more) independent blockchains, each with its own consensus, its own execution environment, and its own assumptions. The bridge must correctly interpret messages from one domain and execute actions in another, without any shared source of truth.

This post covers the specific vulnerability patterns that have caused the largest bridge exploits and what developers building or integrating with bridges should know.


Why Bridges Are Different

A smart contract on a single chain operates within one trust boundary. All state is on that chain. All transactions are validated by that chain's consensus. If the chain is honest, the contract's execution is honest.

A bridge breaks that model. The contracts on Chain A do not know what happened on Chain B. They rely on an intermediary, a set of validators, a light client, an optimistic proof, or a zero-knowledge proof, to tell them what happened. If that intermediary lies, the bridge contracts execute based on false information.

Every bridge exploit ultimately comes down to one failure: the destination chain accepted a message that did not correspond to a real event on the source chain.


Pattern 1: Validator Key Compromise

How it works: The bridge uses a set of validators (often a multisig or a threshold signature scheme) to sign messages attesting that events happened on the source chain. The attacker compromises enough validator keys to forge messages.

Real examples:

  • Ronin Bridge ($625M): 5 of 9 validator keys compromised through social engineering. The attacker signed fraudulent withdrawal messages.
  • Multichain ($130M): The project's CEO held the master keys for the MPC (multi-party computation) system. When they were detained, the keys were compromised.

The vulnerability:

Source Chain:  No deposit happened
Validators:   Compromised keys sign "deposit of 100,000 ETH on source chain"
Dest Chain:    Bridge contract releases 100,000 ETH based on forged signatures

Prevention:

  • Distribute validator keys across independent entities with diverse infrastructure
  • Set the threshold high enough that compromising a majority requires multiple independent breaches
  • Implement withdrawal rate limits: even if validators are compromised, limit how much can leave the bridge per time period
  • Monitor validator behavior and alert on anomalous signing patterns

Pattern 2: Message Verification Bypass

How it works: The bridge contract on the destination chain has a flaw in how it verifies incoming messages. The attacker crafts a message that passes verification without a corresponding event on the source chain.

Real examples:

  • Wormhole ($325M): The Solana-side contract failed to properly verify the guardian signature set. The attacker passed a spoofed SignatureSet account that was not actually signed by the guardians.
  • Nomad ($190M): A routine upgrade accidentally set the trusted root to 0x00. Any message with a zeroed proof was accepted as valid. Once one attacker figured it out, hundreds of others copied the transaction.

The Wormhole vulnerability (simplified):

// Vulnerable: did not verify the SignatureSet account was actually
// created by the Wormhole program with valid guardian signatures
pub fn complete_transfer(ctx: Context<CompleteTransfer>) -> Result<()> {
    let vaa = &ctx.accounts.signature_set; // not properly validated
    // ... releases tokens based on unverified message
}

Prevention:

  • Verify every field of incoming messages: source chain, sender, nonce, payload
  • Use the source program's account ownership to validate that attestation accounts were created by the correct program
  • After upgrades, verify that existing validation logic still functions correctly against test vectors
  • Formal verification of message parsing and validation logic

Pattern 3: Token Mapping Exploits

How it works: The bridge maintains a mapping between tokens on different chains. A wrapped token on Chain B represents a real token locked on Chain A. If the mapping can be manipulated or if the bridge mints wrapped tokens without corresponding locks, value is created from nothing.

The attack:

Attacker: "I deposited 10,000 WETH on Ethereum"
Bridge:   Mints 10,000 wrapped WETH on destination chain
Reality:  No WETH was actually locked on Ethereum

This can happen through:

  • Forged deposit messages (see Pattern 1 and 2)
  • Race conditions between deposit confirmation and mint execution
  • Incorrect handling of token decimals across chains (an 18-decimal token on one chain mapped to a 6-decimal token on another)

Prevention:

  • Always verify deposits are finalized (sufficient block confirmations) before minting
  • Validate token decimal handling explicitly in the bridge logic
  • Maintain accurate accounting: the total minted on the destination should never exceed the total locked on the source

Pattern 4: Replay Attacks

How it works: A valid bridge message is replayed, either on the same chain (to double-claim) or on a different chain (if the message does not include chain-specific identifiers).

The attack:

Step 1: Bridge 100 ETH from Ethereum to Arbitrum (valid message, nonce 42)
Step 2: Replay nonce 42 on Optimism bridge contract
Step 3: Receive 100 ETH on Optimism without a corresponding lock on Ethereum

Prevention:

  • Include a unique nonce in every bridge message and track used nonces on the destination
  • Include the destination chain ID in the signed message
  • Include the destination bridge contract address in the signed message
  • Reject any message with a nonce that has already been processed
mapping(bytes32 => bool) public processedMessages;

function executeMessage(bytes calldata message, bytes calldata proof) external {
    bytes32 messageHash = keccak256(message);
    require(!processedMessages[messageHash], "Already processed");
    processedMessages[messageHash] = true;

    // Verify proof and execute...
}

Pattern 5: Liquidity Drain via Economic Attacks

How it works: The bridge holds liquidity pools on both sides. An attacker manipulates the pool ratios or exploits fee calculation errors to drain liquidity. This is similar to DEX manipulation but across chains, making it harder to detect because the attack spans two independent ledgers.

Prevention:

  • Rate-limit withdrawals: cap the maximum value that can leave the bridge in a given time window
  • Implement circuit breakers: pause the bridge automatically if outflows exceed a threshold
  • Monitor cross-chain accounting in real time and alert on discrepancies

What Bridge Integrators Should Check

If your protocol integrates with a bridge (receiving bridged tokens, executing cross-chain messages, relying on bridged price data), these are the questions to answer:

About the bridge itself:

  • How many validators/guardians does the bridge use, and what is the signing threshold?
  • Are the validator keys held by independent entities or by the bridge team?
  • Does the bridge have withdrawal rate limits?
  • Has the bridge been audited, and when was the most recent audit relative to the current deployed code?

About your integration:

  • Do you verify that bridged tokens are from the expected bridge contract, not an arbitrary address?
  • Do you handle the case where the bridge is paused or messages are delayed?
  • If you use bridged price data, do you have a fallback if the bridge stops relaying?
  • Do you account for token decimal differences across chains?

About your risk exposure:

  • What is the maximum loss if the bridge is fully compromised?
  • Can you pause your protocol's bridge-dependent functions independently?
  • Do you monitor bridge health as part of your operational monitoring?

The Hard Truth About Bridge Security

Bridges are the most complex smart contract systems in production. They combine multi-chain state management, cryptographic verification, economic incentive design, and operational security into a single system. Every bridge exploit has a different proximate cause, but the root cause is always the same: the destination chain trusted something it should have verified.

The trend is toward trust-minimized bridges using zero-knowledge proofs or optimistic verification with fraud proofs. These designs reduce the validator trust assumption but introduce new complexity in proof generation and verification.

Until trust-minimized bridges are the norm, every bridge integration is a trust dependency. Treat it as one.


Odin Scan scans your bridge integration code for common vulnerability patterns, including missing message verification, improper token validation, and replay attack susceptibility. It also checks that your contracts handle bridge failure modes gracefully. Start your free trial.