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_sign is a JSON-RPC method that signs arbitrary data with your private key — including complete serialized transactions. Unlike personal_sign (which adds a safety prefix) or signTypedData (which structures the data), eth_sign signs whatever hex you give it, with no protections. A single eth_sign confirmation 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

MethodInput FormatSafety PrefixCan Sign Transactions?Risk Level
personal_signRaw text/bytesYes (\x19Ethereum Signed Message)NoLow
eth_signRaw 32-byte hashNoYesCritical
signTypedData_v4EIP-712 structured dataYes (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:

  1. The dApp sends a hash to sign
  2. You sign it
  3. If that hash is the keccak256 of a serialized transaction, the attacker now has a valid signed transaction
  4. They broadcast it to the network
  5. 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

Walleteth_sign Status
MetaMaskDisabled by default, warns if enabled
RabbyWarns on eth_sign requests
Trust WalletRestricted
Coinbase WalletDisabled
Ledger LiveShows warning, requires explicit blind signing
Trezor SuiteShows warning
FrameConfigurable

Most major wallets now either disable eth_sign entirely or require explicit user opt-in with prominent warnings. But:

  1. Older wallet versions may still have it enabled
  2. Alternative/minor wallets may not have restricted it
  3. Custom wallet integrations (walletconnect with obscure wallets) may still expose it
  4. 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 VectorSigning MethodUser SeesGas CostCan Drain Wallet?
eth_sign phishingeth_signRaw hexFreeYes (signed transaction)
Permit phishingsignTypedData_v4EIP-712 fieldsFreeYes (token allowance)
Permit2 drainsignTypedData_v4EIP-712 fieldsFreeYes (universal allowance)
setApprovalForAllOn-chain txContract dataUser paysYes (all NFTs)
personal_sign abusepersonal_signReadable textFreeIndirectly (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.