Crypto Training
Bridges Threat Model: Message Passing, Trust Assumptions, and How Things Break
Bridges fail at the boundary between chains: verification, finality, replay, and liveness. Treat bridges as protocols with their own consensus.
If you build cross-chain, you’re building a distributed system with adversaries.
A bridge is not “a contract that locks tokens”. It is:
- a message format
- a verification mechanism
- an operational process
- a liveness guarantee (or lack of one)
The question is always: who is allowed to convince the destination chain to mint/unlock?
The verification menu (with honest tradeoffs)#
| Model | What is trusted | Typical failure mode | What to audit first |
|---|---|---|---|
| Multisig / committee | key ops | compromised keys | signer set, upgrades, emergency powers |
| Optimistic (fraud proofs) | watchers exist | watcher failure / censorship | challenge windows, incentives |
| Light client / ZK | consensus verification | complexity bugs | parameter correctness, domain separation |
There’s no “best”. There’s only “where the risk lives”.
Finality is not a boolean#
Most bridge incidents have a finality misunderstanding somewhere:
- origin chain reorg risk
- L2 message finalization assumptions
- sequencing delays
A bridge that mints too early is vulnerable to reorg-based double-mints.
A bridge that waits too long becomes a liveness nightmare.
Replay is the default bug#
If messages are not uniquely consumed, attackers will replay them.
Audit questions:
- Is message id content-addressed (hash of fields)?
- Is it marked as consumed on destination?
- Is there domain separation across chains and bridge instances?
Liveness is a security property#
Even if verification is perfect, bridges can fail in boring ways:
- relayers go down
- validators stop signing
- censorship prevents messages from being delivered
If your application depends on “bridge message must arrive”, you need a fallback.
Integrator rules (if you are building a dApp)#
These are the rules I actually use when integrating bridges:
- Treat bridged messages as adversarial inputs.
- Never assume a token “arrived” because an API says it did.
- Prefer explicit chain ids and explicit domains.
- Model delayed delivery and stuck delivery.
- Don’t let a bridge revert freeze unrelated operations.
A small, useful table (what to log)#
If you ever do incident response, you will want these fields:
| Field | Why you need it |
|---|---|
| origin tx hash | provenance |
| message id hash | replay / dedupe |
| origin chain id + destination chain id | domain |
| destination execution tx hash | final result |
| verifier configuration version | “which rules were active?” |
Further reading#
- Ethereum.org bridge overview: https://ethereum.org/en/developers/docs/bridges/
- L2 messaging concepts (for context): https://github.com/OffchainLabs/arbitrum/blob/master/docs/L1_L2_Messages.md