James Stanley

I semi-deanonymised some MetaMask users, and they were absolutely loaded

Tue 2 May 2017

Yesterday, I published a post about drive-by identification of MetaMask users (and submitted it to /r/ethereum on reddit). The post included an implementation (now disabled) of an attack that could associate website visitors' IP addresses with their Ethereum accounts, with no user interaction required. This is what I found.

The logs

Of around 400 unique IP addresses that accessed the blog post, around 100 submitted Ethereum account addresses to the logging endpoint. That's a higher ratio than expected, although it's likely that the title of the post selected for clicks from MetaMask users.

Of the ~100 MetaMask users, around 2 in 3 were on mainnet. Most of the rest were using Ropsten testnet, but a few were using (distinct) network ids that correspond to very recent Unix timestamps in milliseconds. Most likely private testnets.

Of the mainnet users, I received ~100 unique Ethereum addresses (web3.eth.getAccounts() can return more than one account per user, although most users only had one). Approximately 1 in 3 addresses were completely unused, but the remainder had a combined balance of over 6,000 ETH (about $500,000). Yes, really. From less than 100 users.


Dan Finlay (a MetaMask developer) wrote a handful of reddit comments on the topic. He pointed out that MetaMask considers itself a developer beta (although the MetaMask homepage doesn't mention this). He also pointed out that MetaMask already had a GitHub issue open for this, which implies they intend to fix it eventually.

Given that MetaMask is a developer beta, there is an awful lot of money being entrusted to it.

Irresponsible Disclosure

Nick Johnson (an Ethereum developer) called me out for irresponsibly disclosing the vulnerability. A handful of people defended the full disclosure. I don't think it was a problem.

And besides, if I had disclosed it "responsibly", I wouldn't have been able to use it myself, and where's the fun in that?


Obviously, as much fun as it was to run a live proof of concept, I can't just leave a semi-exploit "in the wild" indefinitely. The original blog post still shows what it finds about users' accounts, but no longer ships the information off to my server.

Furthermore, having access to this semi-identifying information is nothing but a liability, so I have retroactively removed all record of the information, apart from the aggregated analysis in this post.

So it doesn't matter how much money/violence you have to offer, I can't give you the information. You'll just have to run the attack yourself.

If you like my blog, please consider subscribing to the RSS feed or the mailing list: