Wallet dependency compromised

By now, unless you’ve been living under a rock, you will have heard of the recent supply chain exploit that hit Copay - advertised as a “Secure, Shared Bitcoin Wallet” - a dependency hijack in a seemingly unrelated and little know library gotten from NPM.

To be explicit, here’s how it goes down:

  1. Application developer saves time by using a convenient library in the name of time-to-market / religious code reuse / fantastic UX / multi-platform support / etc
  2. Library transitively pulls in a huge amount of libraries, many of which solve a very small task (say, encode base64 or slightly reshape data to streams)
  3. All these small libraries, because they solve a very small task, receive little maintenance - they don’t need it or maintainer moves on to a brave new world where the small task is no longer relevant
  4. Maintainer hands over a random developer that asks for access, pretending to be interested
  5. New maintainer re-uploads compromised version to NPM / favorite-package-repo such that version number doesn’t change
  6. NPM spreads version to all new builds, even if version locks etc are in place

So when reading this, I was reminded of our own journey… it’s been a long one, but I’m happy that we’ve started it by removing a few components whose explicit purpose is to record data and send it off over the internet - we can sleep better at night worrying less about honest mistakes and bugs. I’m also happy that the large dependency list is prominently featured in our wall of… call-it-what-you-like (SEC-7?) - this instills confidence that it will be dealt with.

It was pointed out (@yenda, correct me here please - can’t seem to find the link) before that our own dependency list is well over 1000 libraries, the elephant in the room being react. Can you name 10% of them? Some of these libraries come from NPM. Can you confidently say that event-stream is not one of them?

What can we learn from this event, and how will it affect the priorities of what we do?


npm ls | grep event-stream | wc -l shows 0 at the moment.
But transitive dependencies and the fact that we use node where this dependency hell is a common practice makes it much harder.

Also, this vulnerability was possible (afaik), because JS allows a library A to alter behaviour of objects of a library B as long as A is imported after B.
so theoretically, if you know another popular secure enclave wrapper, you can target specifically it with ease.

The problem is that even with version locking, maintainers of dependencies can upload their project with the same version number. And thus override what you already had locally.

Even if we don’t have event-stream right now, there is zero guarantee that another compromised dependency wouldn’t import it transitively or just do something malicious itself.

The package-lock file contains checksums of all the files downloaded. Our problem is, that we use npm install that overrides this file instead of npm ci that downloads and checks against it. We also have a problem with using npm ci because we can’t upgrade the npm version properly.

So, at least, we can check that npm install doesn’t change package-lock.json and fail to build if it does.

Added to agenda for Core Dev call on Monday. Status Devs Meeting 8 · Issue #8 · status-im/pm · GitHub

1 Like