Supply Chain Attacks on Developers Are the New Root Access

I did not start worrying about supply chain attacks because of a new CVE. I started worrying the day I noticed where the attackers were aiming. For twenty years the model was simple: the internet is hostile, the server is the prize, and you put a wall between the two. Firewalls, VPNs, bastion hosts, WAFs, hardened images, least-privilege IAM on the cloud account. We got good at defending the server.

Then we handed every developer a laptop with more access than the server, and we stopped watching.

That is the whole shift. Attackers are not trying to exploit your production boxes anymore. They are exploiting the person who has access to them. The developer machine holds SSH private keys, GitHub personal access tokens, npm publish credentials, kubeconfig files, Docker and Podman registry logins, cloud CLI credentials, and live browser sessions for Slack, Discord, and Teams. It is the vault. And the supply chain — a package manager that runs arbitrary code the moment you type install — is the cheapest lock to pick.

June 2026 was not a quiet month

This is not a forecast. It is a recap. The last few weeks produced a run of incidents that all point at the same target.

The one that should bother Linux people most is the campaign Sonatype researchers named Atomic Arch. Attackers adopted orphaned and abandoned AUR packages and injected malicious code into the PKGBUILD and .install scripts. Hundreds of AUR packages were compromised. The payloads went straight for the vault: SSH keys, GitHub and npm tokens, browser cookies, Docker and Podman credentials, cloud keys, and Slack, Discord, and Teams session tokens. When a package was built or installed as root, researchers reported persistence and an eBPF rootkit capability. The Arch User Repository has always run on trust. The attackers read the trust model and used it exactly as designed.

On June 1, 2026, multiple npm packages in the @redhat-cloud-services scope were compromised. Orca Security named the attack Miasma: The Spreading Blight, and StepSecurity documented it in parallel. The payload harvested credentials, SSH keys, cloud tokens, cryptocurrency wallets, and AI tool configurations. The root cause was depressingly human: a Red Hat employee’s GitHub account was compromised, and that was enough to push poisoned releases under a name thousands of teams trust by reflex.

Back on May 11, 2026, a supply chain attack hit the TanStack open-source project through a breach of its GitHub Actions, according to Rescana’s analysis. The compromised Actions were used to publish malicious packages. The CI system that exists to ship code became the thing that shipped the attack.

Then there is axios. In 2026, Trend Micro, Phoenix Security, and EndorLabs reported that axios v1.14.1 and v0.30.4 shipped with a hidden remote access trojan delivered through a dependency named plain-crypto-js, after the maintainer account was hijacked. Axios pulls more than 100 million npm downloads a week. There is no meaningful difference between “the maintainer pushed an update” and “the attacker pushed an update” once the account is taken. The download counter does not care who is at the keyboard.

On May 28, 2026, CISA issued an alert covering supply chain compromises that hit Nx Console and a set of GitHub repositories. The detail worth reading twice: threat actors used a prior compromise of Nx developer systems to compromise a GitHub employee’s device through a poisoned VS Code extension, and the payload scraped credentials from every major developer tool on the machine. Around the same window, GitHub rotated signing keys after a supply chain attack in which a payload ran on the next workspace open and pulled credentials from cloud providers and developer tools.

Six incidents. Different ecosystems — Arch, npm, GitHub Actions, VS Code. One target every time. Not the server. The developer.

The developer machine is the new vault

Sit with what is actually on a working engineer’s laptop, because the inventory is the whole argument.

There are SSH private keys, frequently without a passphrase because passphrases are annoying and the agent caches them anyway. There are GitHub personal access tokens, often scoped far wider than the one repo they were minted for. There are npm publish tokens that can push to packages other people depend on. There are cloud CLI credentials sitting in ~/.aws/credentials, in the gcloud application-default file, in the Azure CLI cache. There are kubeconfig files, and more than a few of them carry cluster-admin. There are Docker and Podman registry logins. There are browser sessions still authenticated to Slack, Discord, Teams, and a dozen internal dashboards. And increasingly there are AI tool configurations holding API keys for OpenAI, Anthropic, and whatever else the team wired into its agents.

That is more standing access than most production servers are ever granted. A production box usually has one role, one set of scoped credentials, and a blast radius someone bothered to think about. The laptop has all of them at once, and it is protected by a package manager that runs arbitrary code on install. We spent years arguing about whether to give a service account read or write. The developer machine has both, to everything, and it installs untrusted code for a living.

I have written before about treating agent tool access as an operational boundary rather than a convenience. The dev machine deserves the same respect and almost never gets it, because nobody filed a change request to make it privileged. It just slowly became the most privileged thing in the building.

The attack surfaces, ranked by how cheap they are to exploit

Not all of these cost the same to abuse. Rank them by effort and the picture gets clarifying.

npm preinstall and postinstall hooks

This is the cheapest one, which is why it keeps happening. npm runs lifecycle scripts automatically on install. preinstall runs before the package is even fully in place. This is not a bug and it was never a bug — it is how npm was designed, so that native modules can build themselves. The side effect is that “I added a dependency” and “I executed a stranger’s code” are the same action. The Miasma campaign leaned on binding.gyp to get execution where postinstall restrictions would have blocked it. The axios case showed you do not even need a clever trick. Hijack the maintainer account and the install hook does the rest, on every machine, on the next npm install.

AUR orphan adoption

Nearly as cheap. The AUR lets anyone adopt an abandoned package, and there is no review process for adoption. Once you own the entry, the PKGBUILD runs as your user — or as root if you build with sudo or makepkg -si, which plenty of people do without thinking. Atomic Arch proved hundreds of packages can be flipped silently this way. The attacker spends nothing but patience, waiting for maintainers to drift away from packages they stopped caring about years ago.

VS Code extensions

Also cheap, and badly underrated. Extensions run with full Node.js access on the developer machine. They can read the filesystem, open a terminal, and reach the network. There is no sandbox, no review gate worth the name, and a full trust model. The CISA alert showed exactly how far that goes: one poisoned extension was enough to compromise a GitHub employee’s device. The editor that every developer leaves open all day is a code execution surface with a marketplace in front of it.

GitHub Actions and OIDC

A little more expensive, because it usually requires compromising a repository or its workflows first. The payoff is why attackers pay the price. An Action with id-token: write can mint cloud tokens through OIDC, which means a single compromised Action can hand out short-lived AWS IAM credentials on demand. The CI runner already holds secrets, tokens, and write access to the repository. The TanStack breach showed this is not a thought experiment. Once the pipeline is yours, you are not stealing one credential. You are standing where the credentials are issued.

PyPI install hooks

Less common than npm, same class of problem. setup.py runs on pip install, so a malicious package executes at install time exactly like its npm cousin. The Red Hat incident is the reminder that this is not a JavaScript problem. It is an install-time-execution problem, and every ecosystem that runs build scripts on install shares it.

Why the tools you bought don’t catch this

Here is the uncomfortable part for anyone who has spent a budget on a security stack. Most of it is aimed at the wrong moment.

DAST and SAST scan the code you wrote, not the dependency that runs during install. SBOM tooling tells you what is in your image — it does not tell you what executed on a developer’s laptop at three in the afternoon when they ran npm install. Container isolation does not save you when the secret is mounted into the container, and a tool like Distrobox deliberately exposes $HOME so the experience feels native. Endpoint detection struggles to flag credential exfiltration that rides out over the same HTTPS as a normal package fetch, because to the network it looks like one more install talking to one more registry.

The common thread is timing. The attack happens at install time. Most monitoring is runtime-only. By the time anything you bought is paying attention, the SSH key is already gone. I went through the gaps in the open-source scanning landscape in more detail in an earlier post, and the conclusion holds: these tools are useful for the problem they were built for, and that problem is not this one.

What actually helps, and what only looks like it does

I have been in this long enough to know the rationalizations. “We use a lockfile.” “We’re in containers.” “We have endpoint protection.” Each of those is true and none of them is the whole answer. So here are the principles I actually trust, stated plainly.

Pin dependencies and use lockfiles, and then actually honor them. npm ci installs from the lockfile and fails on drift; npm install quietly rewrites it. Run npm ci in CI and add something like lockfile-lint so a poisoned resolution shows up as a diff a human can reject, not a silent change nobody reads.

Use --ignore-scripts when you do not need build scripts. It breaks packages that rely on native compilation, which is the honest cost, but it closes the install-time execution path for everything that does not genuinely need it. Decide per project rather than leaving the default wide open.

Separate developer credentials from production credentials, without exception. Production keys do not belong on a laptop that runs untrusted code all day. If the only thing standing between a hijacked npm package and your prod cloud account is the file permissions on ~/.aws/credentials, you have already lost; you just do not know the date yet.

Use short-lived credentials. AWS SSO, OIDC, a Vault-issued token with a fifteen-minute life — these change the math completely. A stolen credential that expires before the attacker reads their exfil log is a non-event. A long-lived API key is a permanent liability with your name on it.

Review AUR packages before you install them. Check the maintainer history, the last update date, and whether the package was recently orphaned and re-adopted. Atomic Arch hid in exactly the packages nobody was looking at. Looking is most of the defense.

Run CI/CD with least privilege. Do not hand an Action id-token: write or repository write access it does not need. The TanStack breach turned CI permissions into the attack. Every scope you remove is a token the attacker cannot mint.

And the principle that reframes all the others: assume the developer machine is already compromised, and ask what your blast radius is. What can an attacker reach from that laptop right now, and what can you rotate in ten minutes? If the answer to the second question is “not much,” that is the work, and it is more valuable than any scanner you can buy.

One thing that does not help, despite how much people want it to: containers do not save you if $HOME is mounted inside. I like Distrobox and Podman and wrote about that whole approach, but isolation that mounts your home directory is not isolation against this threat. The malware reads your secrets straight off the mount. The container boundary is real for a lot of problems. This is not one of them.

The old attack, aimed at a softer target

We spent twenty years building firewalls between the internet and our servers. Then we gave every developer a machine with more access than the servers, and protected it with a package manager that runs arbitrary code on install. The supply chain is not a new attack vector. It is the old one — exfiltrate the credentials, then walk in through the front door — just aimed at a softer target.

When I wrote that the bugs were always there and we simply were not looking hard enough, the lesson was about discovery. This is the same lesson wearing the other face. The attack surface was always there. The developer machine was always the vault. Attackers did not invent a new weakness in June 2026. They found the cheapest path to the access they already wanted, and the cheapest path runs through the install step we all treat as routine.

So here is the question I would put to any team before the next npm install finishes: if your most senior engineer’s laptop were quietly emptied tonight, would you know by morning — and how much of what was on it would still be worth stealing by the time you did?