Recently there have been multiple very serious supply chain exploits that have yet to cease causing problems. Security folks laugh and say “least privilege”, “patch hygiene” and shrug at us mere mortals just trying to go about our days in peace.
They are of course right, us normals are way too comfortable downloading random libraries from the internet, some smaller firms do not have the manpower to manually vet every patch before they are applied, but best case pick a slower update ring to have a chance that others discover problems before they get to them.
In some less competent organisations, security is retrofitted – i.e. every environment is locked down with no regard to working processes, meaning productivity grinds to zero.
Just like you can’t apply marinade after the fact, security – and quality – must be built in from the beginning. Everybody knows that – if you can believe it – but it is very hard to find concrete guidance on the public internet on what to do as a developer. This isn’t it either, by the way. If you were hoping for the professional developer’s guide to hardened development environments, this is definitely not it. I’m just some guy on the internet. At work I have highly qualified coworkers that help me whose secrets I cannot spill.
However, I will try to explain what is going on, and give some basic suggestions that improve your security if you are literally at zero right now.
I will only focus on things that are relevant to a developer machine, so things like OAuth hygiene (not allowing random apps access to your apps or your infrastructure) or what exactly secure code looks like are out of scope here.
I keep this stuff vague for the sake of broader applicability, but hopefully the terms I use are easy enough to google for your platform / stack.
What is happening?
A supply chain attack means that instead of bothering with attacking a company directly, the tools that companies use are attacked and have critical data stolen. Once the data looks relevant (crypto wallet keys, AWS keys, OpenAI credentials, signing keys for popular open source libraries et c) they either sell the information off to other criminals, or go on and attack further organisations. This means we have no idea what the total blast radius will become from an attack that first happened in February. Sometimes data hangs around even longer before further exploits can happen.
Far too many attacks are exploiting system administrators and developers. Sadly AI have made these exploits far easier. Even if the user has properly locked down credentials, the malware can still do everything you can do, so you can get a malware to calmly enumerate all of your secrets, your session configuration files, anything in the filesystem you can read that looks like a relevant password or key and upload it. It didn’t hack anything, you just ran a program that did what programs do, and it could still be enough to bring down a whole company. Once on the computer it can sometimes tell the operating system to load malware as part of the process of starting other programs, and transparently investigate any programs you run on your computer to see what other things you offer up.
What is happening? Well, many things, but one avenue of attack is adding code that runs as soon as a python library is imported. If you ask cursor to solve a problem, it will create a requirements.txt file and if you just import it and aren’t aware of specific versions, you can be owned right there. Other package managers of various forms have similar initialisation code that can be exploited. For operating system packages you need to elevate before it gets to do anything, but today’s bad guys do not need elevated privileges, they do harm with your information alone.
But I am using a Mac, that means it’s secure, right?
Yes and no. The security culture on a Mac is far better than it has historically been on Windows. You have to elevate to do administrative things, the normal user has limited access to make system wide attacks, it’s harder to cryptolock your computer than an old Windows computer on a dodgy network.
But the problem with the latest attacks is that they do not ransom you directly, they just silently steal thing things you may rely on in your daily work.
Also, olden day security culture meant things like having a “secure” folder called ~/.ssh where you kept keys that let you remote access into other computers or push commits to GitHub. It’s chmod:ed 600, meaning only you – but unfortunately also any malware that runs under your account – can read or write it. This was considered secure when the big threat was your colleagues logged in to the same machine would steal your credentials by accessing the files directly. Today the threat is using your credentials, so anything you can read, the bad guy can read.
The benefit of a UNIX-like environment is that it is relatively easy to create a separate user account that can keep any elevated credentials, meaning you can ensure that your daily driver OS user has nothing seriously dangerous on it that can get stolen whilst browsing the internet. The recommendation is the same on Windows, but it is a lot more cumbersome to use.
What to do then?
Basically, you cannot have anything written down on your account that is sensitive. Unfortunately, we need to get work done, and just like it is unhelpful to yell at people for downloading attachments from email and clicking on them, when their literal job is to download attachments from email and clicking on them, we need to figure out other ways of working.
What about a VM? Sure – if you have the compute horsepower or the money, a developer virtual machine that has no credentials at all on it is helpful. Use command line tools that let you log in via a browser to get temporary credentials when pushing code.
Another option is using dev containers. At some point you will need to give credentials to pull or push code to some remote git repository, and you can write scripts that use docker exec to pass single use credentials into the container for that specific execution. If you need access to cloud resources, either proxy via another container running on your computer or command line tools that temporarily give you specific rights. What is the easiest is up to you. Devcontainers are natively supported by VS Code and Cursor, so a lot of the faff is hidden.
To avoid CI tools automatically upgrading your libraries on the server when you build, you can pin versions of your dependencies and commit those version specifications to the repository. Combine that with some tool like snyk, dependabot and npm audit or similar tools to make sure you get a heads-up when vulnerable versions are out there, you can make conscious decisions to upgrade rather than automatically get pwn3d by a nightly build that accidentally pulled down an exploited 3rd party dependency.
There are local secrets managers you can run rather than have your app read configuration files locally. Even if you use Microsoft’s user secrets for local dotnet development, the secrets are still user readable – obviously – so you are vulnerable to those secrets being read anyway. You would think that cool hacker types would be unaware of how .NET programmers store their secrets on developer machines, but in the day of AI, they will not have to know, they will be told by the AI.
What about when your CI authenticates with *aaS providers or external artefact repositories? General advice is – use short-lived keys that aren’t persisted anywhere, i.e. use OAuth to grant access where possible. When the apps you grant access to are exploited – as some have been in the recent spate of attacks – they will have access to do what its token allowed the app to do when you granted access, so make sure to use whatever tooling helps you reduce scope on the access you give. Yes, the cool security types are right about least privilege as well. On the positive side – tooling has improved so the faff is less overpoweringly tedious. AWS for instance are very good about documenting the least access you need to give when creating IAM roles, which is very useful.
Conclusion
No SSH keys on your machine, don’t casually keep static root cloud credentials around on your computer. The passwords in your cloud based password manager can get stolen either in your browser or via direct attack leveraging an insecure development environment (*cough* *cough* LastPass, Bitwarden), so use tooling to assume roles with temporary credentials whenever you need to do something cloudy.
If you do adminy things that need extraordinary powers, feel free to do so from a separate user account, as there is no need for superpowers whilst browsing programmer blogs.On Linux and Mac that is so easy to set up and use.
Your computer will be exploited. Make sure there is nothing on it that can destroy your life or your livelihood when it gets on the internet. It’s a little bit like the old adage about email, “email like you will one day read it out in a court of law”.