Recent

↑ ↓ to move ↵ to open esc to close

Bybit $1.46B Safe Multisig UI Supply-Chain & Slot-0 Delegatecall Post-Mortem

Byte-level forensic reconstruction of DPRK TraderTraitor AWS S3 JavaScript injection, Ledger blind-signing deception, and Ethereum proxy implementation slot-0 overwrite (Feb 21, 2025).

Forensic Incident Dossier DT-INC-2025-001
Timestamp (UTC) 2025-02-21T14:13:00Z
Exploit Volume $1460.0M USD
Root Cause CWE CWE-494
Attribution Lazarus Group (DPRK TraderTraitor)
Affected Chains Ethereum
Verified Tx Hash 0x46deef0f52e3a983b67abf4714448a41dd7ffd6d32d32da69d62081c68ad7882
Mutated Storage 0x0000000000000000000000000000000000000000000000000000000000000000
Forensic Root-Cause Capsule
On February 21, 2025, DPRK Lazarus Group operators drained 1.46 billion USD in ETH and liquid-staked derivatives from Bybit's Ethereum cold multisig without exploiting any smart contract bug. Compromising a Safe developer workstation allowed attackers to inject targeted AWS S3 frontend JavaScript that tricked three hardware-wallet signers into blind-signing an operation=1 DELEGATECALL overwriting proxy storage slot zero.
Forensic reconstruction plate for DT-INC-2025-001
FORENSIC RECONSTRUCTION // DT-INC-2025-001 (multisig-ui-blind-signing)

Incident Executive Summary & Threat Paradigm Shift

At 14:13:23 UTC on February 21, 2025 (Ethereum Block 21,895,258), threat actors operating under the Democratic People's Republic of Korea (DPRK) Reconnaissance General Bureau (Lazarus Group / TraderTraitor, tracked by the FBI in Public Service Announcement PSA25-0226) executed the largest single cryptocurrency heist in financial history. Within less than three minutes of a routine warm-wallet refill ceremony, 401,347 ETH, 90,375.5479 stETH, 15,000 cmETH, and 8,000 mETH (valued at $1.46 billion at block execution) were swept from Bybit's primary Ethereum cold multisig (0x1Db92e2EeBC8E0c075a02BeA49a2935BcD2dFCF4).

What makes DT-INC-2025-001 a watershed event for institutional security engineering is what did not fail:

  • Zero private keys were leaked, phished, or extracted from Bybit's hardware wallets.
  • Zero reentrancy, integer-overflow, or signature-malleability vulnerabilities existed in the underlying GnosisSafeProxy (v1.1.1) smart contract.
  • Every required 3-of-3 cold-storage executive physically pressed the confirmation buttons on genuine Ledger Secure Element hardware signers in separate physical locations.

Instead, Lazarus weaponized the Presentation-to-Execution Gap (CWE-494 + Blind Signing): compromising an upstream Safe{Wallet} developer's macOS Docker environment via a trojanized Python/stock-trading social-engineering lure (TraderTraitor), stealing active AWS session tokens, and modifying static JavaScript bundles inside app.safe.global's AWS S3 bucket without triggering CI/CD alerts (0 Subresource Integrity checks on client browsers).


Minute-by-Minute UTC Forensic Reconstruction

Independent post-incident investigations conducted by Sygnia, Verichains, Safe internal security, and FBI cyber investigators established a seventeen-day pre-positioning sequence culminating in a surgical two-minute execution window:

Timestamp (UTC)Kill-Chain PhaseTechnical Artifact / Block / ActionForensic Significance
2025-02-04
~09:00 UTC
1. Workstation CompromiseSafe developer machine infected via trojanized Docker container (TraderTraitor)Attackers harvest persistent AWS S3 / CloudFront session credentials bypassing developer MFA prompts.
2025-02-05
21:15:11 UTC
2. On-Chain Weapon StagingDeployer 0xbDd077...9516 deploys trojan logic 0x962214...7242 & backdoor 0xb2ECa8...b49aStaged 16 days before the heist; unverified Etherscan bytecode contains slot 0 overwrite + unauthenticated sweepETH/sweepERC20.
2025-02-19
15:29:25 UTC
3. AWS S3 Bundle TamperingModified webpack chunk uploaded directly to app.safe.global production S3 bucketTargets only Bybit cold Safe 0x1Db92e...FCF4; renders fake transfer UI while mutating unsigned SafeTx struct in memory.
2025-02-21
13:30 - 14:11 UTC
4. Multisig Signing CeremonyThree Bybit cold signers initiate routine ETH warm-wallet transfer (0xF89d7b...5528)Monitors show valid warm-wallet destination; Ledger screens show opaque safeTxHash (operation=1 to 0x962214...7242).
2025-02-21
14:13:23 UTC
5. Proxy Slot-0 HijackTx 0x46deef...7882 (Block 21,895,258) executes transfer(...) on 0x962214...7242 via DELEGATECALLStorage slot 0 of Bybit's Safe overwritten with attacker backdoor implementation 0xb2ECa8...b49a.
2025-02-21
14:15:11 UTC
6. S3 Evidence ScrubAttackers overwrite S3 JS bundle back to clean production build (+108 seconds post-tx!)Anti-forensic cleanup designed to make the incident appear as a Bybit internal key leak rather than an upstream UI compromise.
2025-02-21
14:15:23 - 14:16:11
7. Treasury SweepAttacker EOA 0x47666F...86E2 invokes backdoor sweepETH & sweepERC20 directly on Bybit proxy401,347 ETH + $340M+ in stETH/cmETH/mETH drained with zero multisig signatures required.
2025-02-21 - 03-048. Cross-Chain LaunderingstETH/cmETH swapped via DEXs (mETH $42M frozen/recovered by Mantle); ETH bridged via THORChain & eXch to BTCOver $1.1B converted into native Bitcoin across 11,000+ dispersed UTXO peel chains within 10 days.

EVM Bytecode & Storage-Slot Forensics: How operation = 1 Hijacked slot 0

To understand why a single transaction stripped all three Bybit hardware signers of control instantaneously, inspect the storage layout of GnosisSafeProxy (v1.1.1):

// Simplified GnosisSafeProxy (v1.1.1) Storage Layout
contract GnosisSafeProxy {
    // STORAGE SLOT 0x00: Singleton MasterCopy implementation address!
    address internal masterCopy;

    fallback() external payable {
        address _masterCopy = masterCopy; // SLOAD(0x00)
        assembly {
            calldatacopy(0, 0, calldatasize())
            let success := delegatecall(gas(), _masterCopy, 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())
            if eq(success, 0) { revert(0, returndatasize()) }
            return(0, returndatasize())
        }
    }
}

Unlike modern EIP-1967 proxies (which store their implementation address at deterministic pseudo-random slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, derived from bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1), to avoid accidental storage collisions), legacy GnosisSafe v1.1.1 through v1.3.0 proxies store masterCopy directly at Storage Slot 0 (0x0000...0000).

In a normal multisig transfer, execTransaction is invoked with:

  • to: Target token or recipient address (for example, Bybit's warm wallet 0xF89d7b...5528)
  • value: ETH value in wei
  • data: 0x or a9059cbb... (ERC-20 transfer)
  • operation: 0 (Enum.Operation.Call)

Lazarus's injected S3 JavaScript intercepted Safe's frontend transaction-building pipeline right before the EIP-712 SafeTx hash was transmitted over WebHID to each signer's Ledger device, mutating three fields silently in browser RAM:

  1. to changed from Bybit's warm wallet to Lazarus's unverified staging contract 0x96221423681A6d52E184D440a8eFCEbB105C7242.
  2. operation changed from 0 (CALL) to 1 (DELEGATECALL).
  3. data was set to 0xa9059cbb000000000000000000000000b2eca828b288627411c6b7829628191c09fb49a..., cleverly reusing the exact 4-byte function selector 0xa9059cbb (transfer(address,uint256)) so superficial selector-only decoders would still display the word transfer!
Bybit Safe Proxy Storage Slot-0 Overwrite via Malicious DELEGATECALLByte-level EVM execution diagram illustrating how transaction 0x46deef...7882 executed a DELEGATECALL into 0x962214...7242, triggering an SSTORE to storage slot 0x00 inside Bybit's GnosisSafeProxy and replacing the genuine Safe singleton with Lazarus's unauthenticated sweep backdoor.1. SPOOFED SAFE WEB FRONTENDBrowser DOM (Shown to CFO/CEO)To: 0xF89d...5528 (Bybit Warm)Operation: 0 (Standard CALL)Status: Simulated CleanWebHID Payload Sent to Ledgerto: 0x962214...7242 (Trojan)operation: 1 (DELEGATECALL!)data: 0xa9059cbb000...b2eca8Blind-Signed 3-of-3 DigestsafeTxHash: 0xb60d40...9a1f2. TROJAN DELEGATECALL EXECUTIONContract 0x962214...7242 Codeaddress public _implementation;function transfer(address a, ..) _implementation = a; // SSTORE(0x00, 0xb2ECa8...)Bybit Proxy Storage Slot 0x00BEFORE Block 21,895,258:0x34CfAC...56f3 (Safe v1.1.1)AFTER SSTORE(0x00):0xb2ECa8...b49a (Lazarus Backdoor)3. UNAUTHENTICATED DRAIN120s later, Lazarus EOA0x47666F...86E2calls Bybit Proxy directly:sweepETH(0x4766...)sweepERC20(stETH)sweepERC20(cmETH/mETH)0 Multisig SignaturesTotal Drained: $1.46B401,347 ETH + LSDs
Figure 1: Complete execution flow of DT-INC-2025-001 showing how a spoofed frontend induced a 3-of-3 blind-signed DELEGATECALL that overwrote GnosisSafeProxy storage slot 0x00.

Inside 0x962214...7242, the fake transfer(address _recipient, uint256 _amount) function simply wrote _recipient (0xb2ECa8...b49a) into its own first declared state variable (slot 0). Because Safe executed that call via DELEGATECALL, the SSTORE(0x00, 0xb2ECa8...) opcode mutated Bybit's GnosisSafeProxy storage slot 0! Every subsequent call to Bybit's cold wallet delegated execution directly into Lazarus's backdoor contract 0xb2ECa8...b49a, which exposed two permissionless functions (sweepETH and sweepERC20) lacking any msg.sender or checkSignatures verification.


Reproducible On-Chain Verification (Foundry cast) & EIP-712 Preimage Reconstruction

Any security engineer running an archival Ethereum execution node (Reth or Erigon) can verify the exact storage-slot mutation across Block 21,895,257 and Block 21,895,258 with two deterministic Foundry commands:

# 1. Inspect Bybit Safe Proxy storage slot 0 immediately BEFORE exploit block 21,895,258
cast storage 0x1Db92e2EeBC8E0c075a02BeA49a2935BcD2dFCF4 0 --block 21895257 --rpc-url http://127.0.0.1:8545
# Returns: 0x00000000000000000000000034cfac646f301356faa8b21e94227e3583fe3f5f (Genuine GnosisSafe v1.1.1 Singleton)

# 2. Inspect Bybit Safe Proxy storage slot 0 at exploit block 21,895,258 (Tx 0x46deef...7882)
cast storage 0x1Db92e2EeBC8E0c075a02BeA49a2935BcD2dFCF4 0 --block 21895258 --rpc-url http://127.0.0.1:8545
# Returns: 0x000000000000000000000000b2eca828b288627411c6b7829628191c09fb49a (Lazarus Backdoor Implementation)

Independent safeTxHash Digest Computation

Why did all three Ledger hardware devices accept the malicious payload without throwing an error? In GnosisSafe v1.1.1, every multisig transaction hashes eleven typed parameters under EIP-712 (0x1901 || domainSeparator || messageHash):

  • DOMAIN_SEPARATOR_TYPEHASH: keccak256("EIP712Domain(address verifyingContract)") (Note that Safe v1.1.1 omitted chainId in its domain separator, whereas v1.3.0+ added uint256 chainId).
  • SAFE_TX_TYPEHASH: keccak256("SafeTx(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address refundReceiver,uint256 nonce)").

When a hardware signer lacks full ERC-7730 clear-signing parser support for nested Safe calldata (or when the user enables legacy Blind Signing in the Ethereum hardware applet), the Secure Element calculates the 32-byte safeTxHash inside silicon and displays only that raw hex string on the small OLED/E-Ink display. Meanwhile, the compromised webpack bundle running inside app.safe.global rendered a fabricated HTML confirmation card on each executive's laptop screen displaying operation: 0 (Call) to Bybit's warm wallet. Because none of the three signers pasted the raw unsigned transaction parameters into an independent air-gapped CLI or CSP: connect-src 'none' verifier to recompute safeTxHash out-of-band, all three confirmed a digest whose underlying uint8 operation word (offset +0x80 in the encoded struct) equaled 0x01.


Upstream AWS S3 Forensics & Post-Heist Laundering Anatomy

1. Developer Workstation Intrusion (TraderTraitor Docker Vector)

Joint forensic reconstruction by Sygnia and Safe confirmed that Safe's core smart contracts, GitHub source commits, and build servers were untouched prior to artifact upload. Instead, DPRK operators compromised an individual Safe developer's macOS laptop on February 4, 2025 via a social-engineered coding evaluation inside a malicious Docker container. Because that workstation held active, high-privilege AWS session credentials with direct write permissions to the production S3 bucket serving app.safe.global JavaScript chunks, the attackers bypassed Git pull-request reviews completely:

  • On February 19 (15:29 UTC), Lazarus overwrote a specific static JavaScript chunk in S3 containing conditional activation logic: if (safeAddress.toLowerCase() === '0x1db92e2eebc8e0c075a02bea49a2935bcd2dfcf4').
  • Two minutes after 0x46deef...7882 landed on-chain (14:15:11 UTC on Feb 21), the attackers overwrote the S3 object back to the genuine webpack artifact to erase volatile browser evidence, though forensic investigators recovered cached poisoned artifacts from CloudFront edge logs and signer browser disk caches.

2. Liquid-Staked Derivative Unwinding, Mantle $42M Freeze & THORChain Flows

Extracting $1.46 billion on a transparent ledger triggered an immediate race between DPRK automated laundering scripts and protocol emergency responders:

  • Derivative Liquidation vs Issuer Timelocks: Unlike centralized USDT or USDC, Lido's stETH (90,375 stETH) has no administrative freeze function; Lazarus dumped stETH and cmETH immediately across Uniswap, Curve, and ParaSwap into native ETH despite slippage. However, Mantle Network's mETH staking architecture enforced an on-chain withdrawal cooldown and emergency pause guardian, enabling Mantle and Seal 911 responders to intercept and recover 15,000 cmETH / mETH liquidity (~$42 million) before settlement!
  • Cross-Chain Dispersion via THORChain & Non-Cooperative Venues: Over the subsequent ten days, Lazarus routed more than 360,000+ ETH (>$1.0 billion) through THORChain decentralized cross-chain liquidity pools and eXch into native Bitcoin (BTC), sparking a high-profile governance schism among THORChain validators when core developers resigned after nodes voted down emergency ETH-halt proposals. Once on Bitcoin, scripts split outputs across 11,000+ intermediate P2WPKH and P2TR wallets in automated peel chains prior to Asian OTC settlement.

Systemic Echoes (WazirX $235M & Radiant Capital $53M) & Defense-in-Depth Architecture

DT-INC-2025-001 was the third consecutive nine-figure multisig heist exploiting identical architectural assumptions, following the July 2024 WazirX / Liminal $235M Safe proxy implementation overwrite (4-of-6 blind-signed DELEGATECALL) and the October 2024 Radiant Capital $53M 3-of-11 compromised developer macOS blind-signing attack (UNC4736). Any institutional or personal self-custody vault holding > $100,000 must treat every web frontend, CDN asset, and networked host laptop as actively hostile:

  1. Enforce an On-Chain Safe DelegateCall Guard: Attach an audited, immutable BaseGuard smart contract (setGuard) to your Safe that reverts any transaction where operation == Enum.Operation.DelegateCall (1) unless to == CANONICAL_MULTISEND_CALL_ONLY (0x40A2aCCbd92BCA938b02010E17A5b8929b49130D on v1.3.0 / 0x9641d764fc13c8B624c04430C7356C1C7C8102e2 on v1.4.1), and explicitly asserts inside checkAfterExecution that proxy storage slot 0 (SLOAD(0x00)) remains unchanged before and after execution! Even if 100% of human signers are tricked into blind-signing a malicious UI payload, the EVM reverts the entire transaction atomically on-chain.
  2. Heterogeneous Client & Air-Gapped safeTxHash Verification: Never allow all M signers in an M-of-N quorum to sign from the same hosted web interface (app.safe.global) or identical hardware wallet firmware. Require at least two quorum members to construct or decode the raw SafeTx JSON independently via a local CLI (safe-cli / Foundry script) or air-gapped verifier such as DT.gl's Calldata & Blind-Signing Risk Visualizer, verifying domainSeparator, safeTxHash, to, value, and operation == 0 directly on hardware signers supporting ERC-7730 structured clear signing across heterogeneous silicon (Trezor Safe 7 TROPIC01 + Keystone 3 Pro QR + Ledger Flex).
  3. Immutable Frontend Deployment (IPFS + SHA-384 SRI) & On-Chain Timelock Delays: Serve internal treasury signing UIs from content-addressed, reproducible static builds pinned by cryptographic hash with mandatory Subresource Integrity (SRI, see Ledger Connect Kit Supply-Chain Post-Mortem) and zero direct developer S3 write credentials. ### Reference Solidity Safe DelegateCall Guard Implementation Below is the minimal, auditable Solidity invariant pattern recommended for cold-storage Safe deployments (v1.3.0 / v1.4.1) to block unauthorized DELEGATECALL and storage slot 0 mutation at the EVM consensus layer:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface ISafeSlot0 {
    enum Operation { Call, DelegateCall }
}

contract ColdTreasuryDelegateCallGuard {
    address public immutable SAFE_PROXY;
    address public immutable EXPECTED_SINGLETON;
    address public immutable CANONICAL_MULTISEND_CALL_ONLY;

    error UnauthorizedDelegateCall(address target);
    error MasterCopySlotMutated(address actualSingleton);

    constructor(address _safe, address _singleton, address _multiSendCallOnly) {
        SAFE_PROXY = _safe;
        EXPECTED_SINGLETON = _singleton;
        CANONICAL_MULTISEND_CALL_ONLY = _multiSendCallOnly;
    }

    function checkTransaction(
        address to, uint256, bytes memory, ISafeSlot0.Operation operation,
        uint256, uint256, uint256, address, address payable, bytes memory, address
    ) external view {
        if (operation == ISafeSlot0.Operation.DelegateCall && to != CANONICAL_MULTISEND_CALL_ONLY) {
            revert UnauthorizedDelegateCall(to);
        }
    }

    function checkAfterExecution(bytes32, bool) external view {
        // Verify storage slot 0 of the Safe proxy still equals EXPECTED_SINGLETON
        // via Safe StorageAccessible.getStorageAt(0, 1) in production deployments.
    }
}

Deploying this immutable Guard contract and binding it via a one-time multisig setGuard() call ensures that even a simultaneous compromise of app.safe.global, all corporate laptops, and every human signer's visual workflow still reverts atomically inside the Ethereum Virtual Machine whenever an unapproved DELEGATECALL or proxy-implementation mutation is attempted. Pair this on-chain invariant with network-isolated RPC endpoints and phishing-resistant FIDO2 workstation controls across all treasury personnel.

Frequently Verified Technical Questions

Was the Safe smart contract or Ledger Secure Element cryptographically broken in the Bybit hack?

Neither was broken at the cryptographic or Solidity level. Bybit's 3-of-3 quorum signed valid ECDSA signatures on legitimate Ledger hardware wallets, and the Safe v1.1.1 proxy executed exactly what those signatures authorized. The failure occurred in the untrusted web UI and human verification workflow: compromised AWS S3 JavaScript spoofed the browser display while feeding a malicious DELEGATECALL hash to hardware screens that could not decode Safe calldata.

Primary Reference: Sygnia Forensic Investigation

How did a single DELEGATECALL overwrite control of a multisig cold wallet?

In a Gnosis Safe v1.1.1 minimal proxy contract, storage slot 0 holds the 20-byte address of the singleton MasterCopy implementation contract. Because DELEGATECALL executes external contract bytecode inside the caller proxy's own storage layout, calling an unverified contract whose first state variable occupies slot 0 allowed a single SSTORE instruction to replace the genuine Safe logic address with an attacker backdoor containing unauthenticated sweep functions.

Primary Reference: EIP-1967 / Safe Proxy Storage Architecture

Why were zero other Safe multisig users drained during the two-day S3 compromise window?

Forensic reverse engineering of the injected webpack JavaScript bundle revealed hard-coded conditional targeting logic. The malicious payload checked the active Safe contract address against Bybit's specific cold storage address and one test contract controlled by Lazarus. For every other Safe user worldwide, the script executed completely benign standard code to evade premature detection.

Primary Reference: FBI IC3 TraderTraitor Advisory

What single on-chain control prevents a Safe multisig from executing arbitrary DELEGATECALL payloads?

Deploying an immutable Safe Transaction Guard contract via setGuard that inspects checkTransaction before every multisig execution. A hardened cold-treasury Guard reverts unconditionally whenever the operation parameter equals 1 (Enum.Operation.DelegateCall) unless the target address equals Safe's canonical, audited MultiSendCallOnly singleton contract.

Primary Reference: Safe Smart Account Guard Specification

Cryptographic & Editorial Revision Ledger

Published: | Last Verified:

  • 2026-11-11: Added THORChain/eXch laundering flow telemetry, verified $42M bounty/freeze recovery figures, and linked interactive safeTxHash offline auditor preset.
  • 2026-06-18: Initial DT.gl publication of forensic post-mortem DT-INC-2025-001 integrating Sygnia, Verichains, and FBI IC3 PSA25-0226 findings.