In 2017, an Ethereum user connected to a site claiming to be a “free ETH faucet.” The site requested a signature through eth_sign. The user confirmed — it was free, no gas, seemed harmless.
The signature they produced was for a raw transaction that transferred their entire balance to the attacker. The attacker broadcast it to the network. The funds were gone before the user even closed the browser tab.
This attack was so devastating that most wallet providers eventually deprecated or restricted eth_sign. But the method isn’t fully dead — and phishing kits still exploit wallets that haven’t fully locked it down.
BLUF:
eth_signis a JSON-RPC method that signs arbitrary data with your private key — including complete serialized transactions. Unlikepersonal_sign(which adds a safety prefix) orsignTypedData(which structures the data),eth_signsigns whatever hex you give it, with no protections. A singleeth_signconfirmation can produce a valid transaction that drains your wallet. Most modern wallets have restricted or removed it, but if your wallet still supports it — or if you use an older/alternative wallet — you’re at risk.
What Is eth_sign?
eth_sign is one of the original JSON-RPC methods defined in the Ethereum specification. When a dApp calls eth_sign, it asks the wallet to sign an arbitrary 32-byte hash with the user’s private key.
{
"method": "eth_sign",
"params": ["0xYourAddress", "0xArbitraryHash"]
}
The wallet signs the hash and returns a signature. The problem: that hash can encode anything — including a serialized transaction.
The Three Signing Methods Compared
| Method | Input Format | Safety Prefix | Can Sign Transactions? | Risk Level |
|---|---|---|---|---|
personal_sign | Raw text/bytes | Yes (\x19Ethereum Signed Message) | No | Low |
eth_sign | Raw 32-byte hash | No | Yes | Critical |
signTypedData_v4 | EIP-712 structured data | Yes (EIP-712 domain separator) | No (but can authorize permits) | Medium |
personal_sign adds a prefix (\x19Ethereum Signed Message:\n + length) before hashing. This makes the signature incompatible with transaction signing — the Ethereum protocol doesn’t recognize this prefix in transactions, so a personal_sign signature can’t be replayed as a transaction.
eth_sign adds no prefix. The signature is mathematically identical to what you’d produce if you were signing a transaction. This means:
- The dApp sends a hash to sign
- You sign it
- If that hash is the keccak256 of a serialized transaction, the attacker now has a valid signed transaction
- They broadcast it to the network
- Your transaction executes
How eth_sign Phishing Works
Step 1: The Bait
As with all phishing attacks, the user is lured to a fake site through:
- Hacked social media accounts posting “airdrop” links
- Discord/Telegram messages about “exclusive claims”
- Google Ads targeting crypto-related keywords
- NFT airdrops with metadata containing phishing URLs
Step 2: The eth_sign Request
The phishing site connects to the victim’s wallet and immediately calls eth_sign. The request contains a hash — but it’s not a random verification hash. It’s the keccak256 of a serialized transaction that does one of the following:
- Calls
approve(attackerContract, MAX_UINT)on an ERC-20 token - Calls
transfer(attackerAddress, fullBalance)on a token - Calls
setApprovalForAll(attackerContract, true)on an NFT contract - Signs a Permit2 message granting token allowances
Step 3: What the User Sees
The wallet shows something like:
Request to sign:
0x4e7123456789abcdef0123456789abcdef012345678
9abcdef0123456789abcdef0123456789abcdef012345
Just raw hex. No explanation of what it means. No decoded function name. No amount or recipient.
This is essentially blind signing — but worse, because even sophisticated users can’t decode a keccak256 hash by looking at it.
Step 4: The Drain
The attacker takes the signature and reconstructs the full transaction. They broadcast it to the network (paying the gas themselves). The transaction executes as if the user had sent it directly.
Why eth_sign Is So Dangerous
Problem 1: No Content Verification
With personal_sign, the wallet displays the actual message text — “Sign in to DApp,” “Verify ownership,” etc. The user can read and judge the content.
With eth_sign, the wallet displays a hash. A hash is a one-way function — you cannot reverse-engineer what data it represents. Even if the wallet wanted to show the user what they’re signing, it can’t — it only has the hash, not the original data.
This is the fundamental flaw: you’re signing something without knowing what it is.
Problem 2: Signature = Transaction
An eth_sign signature can be used to construct a valid Ethereum transaction. This isn’t a “theoretical” risk — it’s the exact mechanism by which all Ethereum transactions are signed. The only difference is context: when you send a transaction normally, your wallet constructs the transaction, signs it, and broadcasts it. With eth_sign phishing, the attacker constructs the transaction, tricks you into signing it, and broadcasts it.
Problem 3: No Replay Protection
Unlike EIP-712 typed data (which includes a chain ID and domain separator to prevent cross-chain replay), eth_sign signatures have no built-in replay protection. A signature valid on Ethereum mainnet could potentially be replayed on a fork (though EIP-155’s chain ID protection mitigates this for modern transactions).
Current Wallet Support Status
| Wallet | eth_sign Status |
|---|---|
| MetaMask | Disabled by default, warns if enabled |
| Rabby | Warns on eth_sign requests |
| Trust Wallet | Restricted |
| Coinbase Wallet | Disabled |
| Ledger Live | Shows warning, requires explicit blind signing |
| Trezor Suite | Shows warning |
| Frame | Configurable |
Most major wallets now either disable eth_sign entirely or require explicit user opt-in with prominent warnings. But:
- Older wallet versions may still have it enabled
- Alternative/minor wallets may not have restricted it
- Custom wallet integrations (walletconnect with obscure wallets) may still expose it
- Phishing kits specifically target wallets known to still support it
How to Know If You’re Vulnerable
Check 1: Wallet Settings
Search your wallet settings for “eth_sign,” “blind signing,” or “contract data.” If you find a toggle and it’s enabled, you may be vulnerable.
Check 2: Test with a Safe Site
Some security tools let you test whether your wallet allows eth_sign:
- julien-dev/signing — ConsenSys signing examples
- Various wallet security audits include eth_sign testing
Check 3: Keep Your Wallet Updated
If you’re running the latest version of MetaMask, Rabby, or Trust Wallet, eth_sign is already restricted. The risk is primarily for outdated or obscure wallets.
Defense Against eth_sign Phishing
1. Update Your Wallet
Ensure you’re running the latest version of your wallet software. Major wallets have deprecated eth_sign — newer versions are safe.
2. Never Sign Hex Data
If your wallet shows raw hex data (0x...) instead of readable text or structured EIP-712 data, do not sign. This is the universal warning sign of a dangerous signing request.
3. Use Simulation Tools
Tools like Rabby Wallet, Pocket Universe, and Blockaid simulate signing requests and show the outcome before you confirm. If the simulation shows asset loss, reject immediately.
4: Use Hardware Wallets (With Caveats)
Hardware wallets add a physical confirmation step, but as explained in our blind signing guide, they can’t decode eth_sign data either. The hardware wallet forces you to pause and think — which is helpful but not foolproof.
5: Check Site Legitimacy
Before connecting your wallet, verify the site:
- Domain matches official documentation exactly (check for homoglyphs)
- Navigate from a saved bookmark
- Check if the site’s contract is flagged on our address risk scoring API
eth_sign vs. Other Signature Attacks
| Attack Vector | Signing Method | User Sees | Gas Cost | Can Drain Wallet? |
|---|---|---|---|---|
| eth_sign phishing | eth_sign | Raw hex | Free | Yes (signed transaction) |
| Permit phishing | signTypedData_v4 | EIP-712 fields | Free | Yes (token allowance) |
| Permit2 drain | signTypedData_v4 | EIP-712 fields | Free | Yes (universal allowance) |
| setApprovalForAll | On-chain tx | Contract data | User pays | Yes (all NFTs) |
| personal_sign abuse | personal_sign | Readable text | Free | Indirectly (rare) |
The full taxonomy of signature scams covers all these variants.
Frequently Asked Questions
Q: If eth_sign is deprecated, why should I care?
A: Two reasons. First, some wallets still support it — especially older versions or lesser-known wallets. Second, understanding eth_sign helps you understand why “signing” is dangerous in general. The core lesson (never sign what you can’t read) applies to every signing method.
Q: What should I do if I already signed an eth_sign request?
A: Immediately move all assets to a fresh wallet. If the attacker has a valid signed transaction, they can broadcast it at any time — now or months from now. Assume the signature is compromised and act fast.
Q: Can I undo an eth_sign signature?
A: No. Cryptographic signatures cannot be revoked. The only defense is to move your assets before the attacker uses the signature to execute a transaction. Nonce-based protections exist (EIP-712 includes nonces for some permit types), but raw eth_sign has no such mechanism.
Q: Is MetaMask safe from eth_sign attacks?
A: Modern MetaMask versions disable eth_sign by default. If you haven’t tampered with developer settings, you’re protected. But always keep MetaMask updated and don’t enable experimental signing features unless you understand the risks.
Q: What’s the difference between eth_sign and personal_sign technically?
A: personal_sign prefixes the message with \x19Ethereum Signed Message:\n + message length before hashing. This prefix makes the signature structurally incompatible with transaction encoding — Ethereum’s transaction format doesn’t include this prefix. eth_sign signs the hash directly, making the signature structurally identical to a transaction signature.