<< All versions

Skill v1.0.0

currentAutomated scan100/100
bittersecurity/decepticon/bridge-exploit
──Details
PublishedOctober 14, 2026 at 02:30 AM
Content Hashsha256:8e9ba92bace19199...
Git SHA39fdf37d42a5
──Files
Files (1 file, 5.4 KB)
SKILL.md5.4 KBactive
SKILL.md · 116 lines · 5.4 KB

version: "1.0.0" name: contracts-bridge-exploit description: "Cross-chain bridge attack — message-validation bypass (Wormhole class), validator key compromise (Ronin / Harmony class), reentrancy on token-bridge claim, Merkle-proof forgery on optimistic bridges, signature replay across chains. Bridges have lost >$2B; understand why." allowed-tools: Bash Read Write metadata: when_to_use: "bridge cross-chain wormhole ronin harmony nomad multichain anyswap layerzero axelar relayer validator merkle optimistic" subdomain: contracts tags: defi, bridge, cross-chain, validator mitre_attack: T1190, T1565


Cross-Chain Bridge Attack

Bridges hold large pooled assets and execute messages from a separate trust layer. Architecturally fragile.

Bridge taxonomy

TypeTrust modelPast exploits
Lock-and-mintTrusted validators sign mint eventsWormhole ($325M), Ronin ($600M), Harmony ($100M)
Burn-and-redeemSameMultichain/Anyswap ($126M)
OptimisticFraud proof windowNomad ($190M)
Light-client / zkCryptographic(Fewer hacks, but newer)
Liquidity-network (Hop, Connext)Routers + relayersSmaller individual exploits

Attack classes

1. Validator-signature bypass (Wormhole, Feb 2022, $325M)

The Solana-side verify_signature function trusted the caller to provide a "verified" sigset account. Attacker passed a sysvar that wasn't a real sigset → unauthorized mint of 120k wETH.

Lesson: any verify function whose input is a struct fetched by address is bypassable if address-trust is missing.

2. Validator key compromise (Ronin, March 2022, $600M)

9-of-9 validators, 5 of which were operated by one entity. Sky Mavis got phished → attacker controlled 5 keys → arbitrary mint.

Lesson: validator decentralization isn't math, it's operational. Count distinct legal entities and key-storage methods, not just keys.

3. Merkle-proof forgery (Nomad, August 2022, $190M)

After an upgrade, the zero-hash was set as a "valid root" — any proof against root = 0 passed. The first attacker withdrew real funds; then thousands of others copy-pasted the same tx with their own address. ~$190M total.

Lesson: check initialize / upgrade scripts for accidental defaults — bytes32(0), address(0), 1 (often the most-tested value) becoming the trusted value.

4. Replay across chains (Multichain class)

Bridge tx signed for chain A is replayed on chain B because chainId wasn't bound into the signed message:

solidity
function claim(bytes32 nonce, uint256 amount, bytes calldata sig) external {
bytes32 hash = keccak256(abi.encode(nonce, msg.sender, amount)); // ⚠ no chainId
require(ecrecover(hash, ...) == validator);
token.transfer(msg.sender, amount);
}
// On chain A: legit claim
// On chain B (same validator, same token): replay the same sig

5. Reentrancy on bridge claim

Claim transfers tokens THEN updates nonce-used mapping:

solidity
function claim(...) external {
token.transfer(msg.sender, amount); // attacker token w/ callback
used[nonce] = true; // updated AFTER
}
// ERC777 / ERC1363 / malicious ERC20 callback → re-enter claim same nonce

6. Liquidity-pool draining via fee oracle (Hop / Across class)

Bridges using a quote-and-relay model price slippage via oracle. Manipulate the oracle → arbitrage drains liquidity:

Step 1: Borrow large position on chain A
Step 2: Manipulate underlying spot price oracle that bridge fee uses
Step 3: Initiate cross-chain transfer at the manipulated rate
Step 4: Repay loan, profit = bridge fee discount on a large transfer

Bridge audit checklist (the bugs that broke real bridges)

  1. `verify_signature` trust chain: from where does the verifier load its trust roots? Can the caller spoof them?
  2. Validator set update: is there a quorum check on changing validators? Can a 51% rotate themselves out and stay in?
  3. Nonce vs chainId binding: does the signed message include destChainId?
  4. Claim state machine: nonce-used mapping written BEFORE external token call?
  5. Default values: any address(0), bytes32(0), 1 in initialize that becomes a trusted value?
  6. Pause / rescue functions: are they gated by a multisig that's actually distributed?
  7. Relayer trust: does the bridge trust relayer-provided data, or re-verify on-chain?
  8. Fee/rate oracle: TWAP or spot? Manipulable?

Tooling

bash
# Foundry test against a fork — simulate the exact bridge flow
forge test --fork-url $RPC --match-contract Bridge --fork-block-number 17000000
# Slither — finds reentrancy + signature-replay heuristics
slither <project>
# Echidna — fuzz the bridge claim function with arbitrary calldata
echidna-test test/Bridge.t.sol --config echidna.yaml
# Tenderly — live simulation against deployed bridge contracts

OPSEC / scope

  • Bridge attacks are direct financial theft. Never test against live bridges without explicit ownership/written authorization.
  • Bug bounty bridges (Immunefi top payouts) are the legitimate channel — read the Immunefi scope, then test on a private fork.
  • Disclose responsibly — bridge maintainers may need 24-72h to drain liquidity to a safe vault.

References

  • Rekt.news — every major bridge hack post-mortem
  • Trail of Bits "Cross-Chain Bridge Architecture" deep dive
  • Wormhole / Ronin / Harmony / Nomad post-mortems (official)
  • "How to Build a Secure Cross-Chain Bridge" — Chainlink Labs research
All versions