Hacktricks-skills web3-signing-workflow-compromise
Analyze and detect Web3 signing workflow compromises, Safe{Wallet} delegatecall proxy takeover attacks, and EIP-712 signature manipulation. Use this skill whenever the user mentions Safe wallets, multisig security, delegatecall vulnerabilities, proxy storage slot attacks, signing UI compromises, EIP-712 signature issues, or any Web3 wallet security audit. Also trigger for cold-wallet security reviews, transaction signing validation, or when investigating potential wallet takeover incidents.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/blockchain/blockchain-and-crypto-currencies/web3-signing-workflow-compromise-safe-delegatecall-proxy-takeover/SKILL.MDWeb3 Signing Workflow Compromise & Safe Delegatecall Proxy Takeover
A skill for analyzing and detecting sophisticated Web3 wallet compromise patterns involving signing workflow manipulation and on-chain delegatecall proxy takeovers.
What This Skill Covers
This skill helps you understand and detect a specific attack chain that combines:
- Off-chain supply-chain compromise of signing UI (e.g., Safe{Wallet} web interface)
- On-chain delegatecall primitive abuse to overwrite proxy implementation pointers
The pattern was used in major incidents including the February 2025 Bybit cold-wallet drain (~401k ETH).
Attack Pattern Overview
The Two-Stage Attack
Stage 1 (Off-chain): Compromised signing UI ├── Tampered JS bundle injected into Safe{Wallet} ├── Context-gated: only triggers for specific Safe + signer addresses ├── Mutates transaction fields immediately before signing ├── Restores original UI data after signature is obtained └── Victim signs attacker-chosen payload without knowing Stage 2 (On-chain): Delegatecall proxy takeover ├── Safe proxy executes delegatecall (operation=1) to attacker contract ├── Attacker contract writes to storage slot 0 (masterCopy pointer) ├── Proxy implementation now points to attacker logic └── Full wallet control achieved
Key Technical Details
Storage Slot Collision: Safe proxies store
masterCopy (implementation address) at storage slot 0. Because Safe supports operation = 1 (delegatecall), any signed transaction can execute arbitrary code in the proxy's storage context.
The Malicious Contract Pattern:
// Attacker contract mimics ERC-20 transfer but writes slot 0 uint256 stor0; // slot 0 function transfer(address _to, uint256 _value) external { stor0 = uint256(uint160(_to)); // Overwrites masterCopy! }
The Signing Mutation:
// Pseudocode of the malicious flow orig = structuredClone(tx.data); if (isVictimSafe && isVictimSigner && tx.data.operation === 0) { tx.data.to = attackerContract; tx.data.data = "0xa9059cbb..."; // ERC-20 transfer selector tx.data.operation = 1; // delegatecall tx.data.value = 0; tx.data.safeTxGas = 45746; const sig = await sdk.signTransaction(tx, safeVersion); sig.data = orig; // restore original before submission tx.data = orig; return sig; }
Detection Checklist
Use this checklist when auditing Safe wallets or investigating potential compromises:
UI Integrity Checks
- Pin JS assets: Verify SRI (Subresource Integrity) hashes on all signing UI bundles
- Monitor bundle diffs: Alert on any changes to
or similar critical files_app-*.js - Check Wayback Machine: Compare current bundles against historical snapshots
- Verify CDN integrity: Ensure signing UI is served from expected, verified sources
Transaction Analysis
- Flag delegatecall operations: Any
from treasury wallets should trigger reviewoperation = 1 - Decode nested calldata: Don't trust UI rendering; decode
to see actual function callstx.data - Verify safeTxHash: Recompute hash and validate it matches the signed data
- Check operation changes: Alert if
differs from typical patterns (most areoperation
)call
Server-Side Validation
- Hash verification: Gateways must recompute
and validate signatures match submitted fieldssafeTxHash - Signature-data consistency: Reject proposals where signature corresponds to different fields than JSON body
- Policy enforcement: Implement preflight rules for
, selectors, and asset typesto
Contract Design Review
- Guard installation: Safes >= v1.3.0 can install Guards to veto delegatecall or enforce ACLs
- Slot collision risk: Avoid placing upgrade pointers at slot 0 if delegatecall is possible
- Delegatecall necessity: Question whether arbitrary delegatecall is truly needed in multisig/treasury
Hardening Recommendations
Immediate Actions
- Upgrade Safe contracts to v1.3.0+ to enable Guard functionality
- Install a Guard that vetoes
operations or enforces strict ACLsdelegatecall - Implement server-side hash verification on any signing-orchestration API
- Pin and monitor all signing UI assets with SRI hashes
Policy Changes
- Disallow delegatecall except for vetted, whitelisted flows
- Require internal policy service approval before broadcasting fully signed transactions
- Implement clear-signing on hardware wallets that explicitly renders
and decodes nested calldataoperation - Set up monitoring for delegatecall executions from wallets holding treasury funds
Architectural Improvements
- Separate signing from execution: Use a policy service that validates transactions before they're signed
- Multi-layer verification: Require independent verification of transaction parameters at signing time
- Storage slot isolation: Place upgrade pointers away from slot 0 or guard with explicit upgrade logic
- Bundle integrity: Serve signing UI from immutable, versioned sources with cryptographic verification
Real-World Incident: Bybit February 2025
Timeline
- February 21, 2025: Bybit cold-wallet drained (~401k ETH)
- Attack vector: Compromised Safe S3 bundle (
)_app-52c9031bfa03da47.js - Targeting: Hard-coded allowlist for Bybit's Safe (
) and signer addresses0x1db9…cf4 - Cleanup: Bundle rolled back to clean version 2 minutes after execution
Attack Flow
- Compromised bundle loaded in Safe{Wallet} web UI
- Context-gated logic detected Bybit Safe + signer addresses
- Transaction mutated:
→operation=0
,1
→ attacker contractto - Victim signed the mutated transaction (EIP-712 signature)
- UI restored original data before submission
- Safe Client Gateway accepted proposal (pre-hardening)
- Transaction executed: delegatecall to attacker contract
- Attacker contract wrote slot 0, overwriting
masterCopy - Proxy implementation now attacker-controlled
- Funds swept via
functionssweepETH/sweepERC20
Post-Incident Hardening
- Safe Client Gateway now rejects proposals where hash/signature don't match submitted transaction
- Similar server-side verification should be enforced on any signing-orchestration API
When to Use This Skill
Trigger this skill when you need to:
- Audit Safe{Wallet} or similar multisig security
- Investigate potential wallet compromise incidents
- Review transaction signing workflows for vulnerabilities
- Analyze EIP-712 signature security
- Design hardening measures for treasury wallets
- Understand delegatecall proxy attack patterns
- Review storage slot collision risks in proxy contracts
- Investigate supply-chain compromises in Web3 signing UIs
References
- AnChain.AI forensic breakdown of the Bybit Safe exploit
- Zero Hour Technology analysis of the Safe bundle compromise
- In-depth technical analysis of the Bybit hack (NCC Group)
- EIP-712 Specification
- safe-client-gateway (GitHub)
Quick Reference: Attack Indicators
| Indicator | What to Look For | Risk Level |
|---|---|---|
| Delegatecall from treasury wallet | 🔴 Critical |
| Slot 0 writes | Any contract writing to storage slot 0 in proxy context | 🔴 Critical |
| UI bundle changes | Unverified changes to signing UI JS files | 🟠 High |
| Hash mismatch | doesn't match signed data | 🔴 Critical |
| Context-gated logic | Hard-coded address allowlists in signing code | 🟠 High |
| ERC-20 selector abuse | (transfer) to non-ERC-20 contract | 🟡 Medium |