I have become fairly paranoid about running random repositories on my normal development computer.
I don’t mean that I assume every GitHub repo is malware. Most aren’t. But developers are valuable targets, especially anyone working with blockchain, cloud systems, production infrastructure, or source code that may have credentials attached to it.
I see enough suspicious repositories that I don’t think running unknown code on my primary system is worth the risk.
My solution is pretty simple. I use disposable development systems.
For a simple project, especially something like a Node server, I usually spin up a small Linux server in the cloud.
Install Node, clone the repo, look through it, and run it there.
There isn’t much on the server to steal. It doesn’t have my browser sessions, normal SSH keys, crypto wallets, personal files, or credentials for unrelated projects.
When I’m done, I delete the server.
If something malicious does run, I would much rather throw away a $5 or $10 cloud VM than try to figure out what happened on my main development computer.
For more complicated projects, a command line Linux server isn’t always enough.
Sometimes I need a browser, VS Code, multiple development tools, Docker, or just a normal desktop environment.
For those I built a basic Linux development desktop with the tools I normally use.
The slightly unusual part is the hardware.
I use an older laptop with no internal hard drive at all. I boot Linux from an external USB SSD (Inexpensive, Less than $20).
Everything is on that SSD. The operating system, development tools, repos, temporary files, and anything else created while working with the code.
I keep several SSDs around, so making another clean development system is easy.
I can start cloning a known clean Linux installation to another SSD in the background while I’m doing something else. A few minutes later I have what is effectively a fresh development computer.
If I run across something suspicious, I don’t need to spend hours trying to determine if malware survived somewhere on the system.
I wipe the SSD and start over.
That is one of the parts I like most about this setup.
Trying to prove that a compromised machine is clean can take far longer than simply replacing the installation.
I also try not to defeat the purpose of the disposable machine by immediately putting valuable credentials on it.
I don’t sign into my normal browser profile.
I don’t put a funded crypto wallet on it.
I don’t copy over my normal SSH keys.
I don’t give it AWS administrator credentials.
I don’t put my password manager on it.
If a project needs credentials, I try to create temporary credentials with the minimum permissions needed for that particular project.
A disposable computer isn’t very disposable if compromising it also gives someone access to everything else you own.
Network access is worth thinking about too.
A computer can have nothing valuable stored locally and still be able to attack other systems on the same network.
For code that I am particularly suspicious of, I don’t necessarily want the machine sitting on the same trusted network as everything else.
A guest Wi-Fi network, separate VLAN, or firewall rules can add another useful layer.
Virtual machines are another perfectly good way to do this. I use those too.
I just like having a completely separate physical development environment.
There are no shared host directories unless I deliberately create them. The machine behaves like a normal Linux computer. Browsers, Docker, IDEs, USB devices, and development tools all work normally.
The SSD is basically the machine.
Remove it or wipe it and the development environment is gone.
I also run my repo_malware_scan against unknown repositories before I start working with them. That gives me another layer and has caught enough strange things that I consider it worthwhile.
But I don’t assume any scanner can find everything.
That is really the point of using a disposable environment.
I don’t need to be 100 percent certain that a repository is safe before looking at it.
I need to make sure the consequences are limited if it isn’t.
Developers run a lot of code written by people they don’t know.
Clone the repo.
Run npm install.
Open it in an IDE.
Run Docker.
Run a setup script.
Start the development server.
Every one of those steps gives the repository some level of trust.
So instead of only asking whether I think a repository is safe, I try to ask a different question:
What happens if I’m wrong?
If the answer is “wipe an SSD” or “delete a temporary cloud server,” I am much more comfortable finding out.