The Address the Signers Never Saw: A Wallet Bundle Swap
The challenge
Brynmor's signers approved a routine transfer. Find where the app's code swaps the recipient. Name the address the transaction really goes to.
What you'll learn
- Spot injected code gated on specific wallet addresses
- Tell victim addresses in a target list from the attacker's address
- Explain what operation 1 (delegatecall) lets a Safe transaction do
- Understand why a signer's screen can differ from what gets signed
- Name controls against front-end tampering and blind signing
Skills tested
Prerequisites
- Reading JavaScript
- What a multisig wallet is
How it works
A Safe multisig executes a transaction only once enough owners have signed its fields: to, value, data and operation. Owners usually sign through a web app, so whoever controls that app's JavaScript controls what actually gets signed.
operation is 0 for a normal call and 1 for a delegatecall. A delegatecall runs the target contract's code inside the Safe itself, with the Safe's balance and storage, so one signed delegatecall to an attacker's contract hands over the whole wallet.
In February 2025 attackers did exactly this to Bybit: JavaScript injected into the Safe{Wallet} front end waited for the exchange's cold-wallet Safe, swapped a routine transfer for a delegatecall, and restored the display after signing. The attacker's contract then swept about 401,000 ETH and other tokens, roughly 1.5 billion dollars.
Common mistakes
- Answering the warm wallet (0x0Ac51AA8300882aAa03F7678770495345Dc51774). That is what the review screen showed and what the signers believed they approved. The bundle overwrites
tobefore signing and restores it after. - Answering an address from
waorba. Those lists are the targets: Brynmor's own Safe and signers, as queued-tx.json shows. They decide when the trap fires, not where the money goes. - Trusting the decoded calldata.
0xa9059cbbis the selector oftransfer(address,uint256), so a wallet shows a zero-value transfer. With operation 1 the attacker's contract decides what that call really does.
How to defend against it
- Verify every multisig transaction on an independent device: hardware-wallet clear signing of
to,operationand decodeddata, or asafeTxHashrecomputed with an offline tool, never only the web page. - Treat
operation: 1as critical: a Safe Guard can reject delegatecall except to allowlisted libraries such as MultiSend. - Pin the wallet front end to a reviewed build (self-hosted or content-addressed), monitor the served bundle's hash, and lock down who can write to the hosting bucket.
- Keep cold-wallet signing on dedicated machines and follow a written checklist for large moves.