TL;DR: I wrote a little program to build and test software in a pair of nested virtual machines, to reduce the risk of bugs or malware in dependencies doing bad things. It’s called the Contractor and it’s just barely usable now. Feedback welcome.

Software development is a security risk.

Building software from source code and running it is a core activity of software development. Software developers do it on the machine they use for other things too. The process is roughly as follows:

  • install any dependencies
  • build the software
  • run the software, perhaps as part of unit testing

When the software is run, even if only a small unit of it, it can do anything that the person running the build can do, in principle:

  • delete files
  • modify files
  • log into remote hosts using SSH
  • decrypt or sign files with PGP
  • send email
  • delete email
  • commit to version control repositories
  • do anything with the browser that a the person could do
  • run things as sudo
  • in general, cause mayhem and chaos

Normally, a software developer can assume that the code they wrote themselves doesn’t do any of that. They can even assume that people they work with don’t do any of that. In both cases, they may be wrong: mistakes happen. It’s a well-guarded secret among programmers that they sometimes, even if rarely, make catastrophic mistakes.

Accidents aside, mayhem and chaos may be intentional. Your own project may not have malware, and you may have vetted all your dependencies, and you trust them. But your dependencies have dependencies, which have further dependencies, which have dependencies of their own. You’d need to vet the whole dependency tree. Even decades ago, in the 1990s, this could easily be hundreds of thousands of lines of code, and modern systems a much larger. Note that build tools are themselves dependencies, as is the whole operating system. Any code that is used in the build process is a dependency.

How certain are you that you can spot malicious code that’s intentionally hidden and obfuscated?

Are you prepared to vet any changes to any transitive dependencies?

Does this really matter? Maybe it doesn’t. If you can’t ever do anything on your computer that would affect you or anyone else in a negative way, it probably doesn’t matter. Most software developers are not in that position.

This risk affects every operating system and every programming language. The degree in which it exists varies, a lot. Some programming language ecosystems seem more vulnerable than others: the nodejs/npm one, for example, values tiny and highly focused packages, which leads to immense dependency trees. The more direct or indirect dependencies there are, the higher the chance that one of them turns out to be bad.

The risk also exists for more traditional languages, such as C. Few C programs have no dependencies. They all need a C compiler, which in turn requires an operating system, at least.

The risk is there for both free software systems, and non-free ones. As an example, the Debian system is entirely free software, but it’s huge: the Debian 10 (buster) release has tens of thousands of software packages, maintained by thousands of people. While it’s probable that none of those packages contains actual malware, it’s not certain. Even if everyone who helps maintain is completely trustworthy, the amount of software in Debian is much too large for all code to be comprehensively reviewed. Also, no amount of review will catch all bugs.

This is true for all operating systems that are not mere toys.

The conclusion here is that to build software securely, we can’t assume all code involved in the build to be secure. We need something more secure. The Contractor aims to be a possible solution.

See the README for instructions how to try it. See the subplot document for more about the architecture and so on for how it works.

The Contractor has only just reached a state where it can build and test some of my other projects. It’s ugly, buggy, and awkward, but I expect to have much fun using and improving it in the future. Maybe you’d like to join the adventure?