What Does the Left-Pad Incident Teach Us About Modern Supply Chain Attacks?
Left-pad proved that one maintainer's decision reaches every build on the planet within minutes. In 2016 that decision was an unpublish. Today it is a poisoned release pushed from a stolen account. The mechanism between the two is unchanged: npm resolves transitive dependencies automatically, installing runs code, and the registry treats maintainer authority as the only gate. The left-pad incident was the proof of concept, and current attackers work from that blueprint.
What Happened in 2016
On 22 March 2016 Azer Koçulu unpublished every package he had on npm. One of them was left-pad, eleven lines that pad a string. Builds broke across Babel and React, and downstream at Facebook, PayPal, Netflix and Spotify. npm restored the package by hand within hours, then limited unpublishing to a 24-hour window for packages others depend on. Their write-up from that week is still online.
Left-Pad Was Not an Accident
The blast radius was accidental. The act was not. Koçulu removed his packages deliberately, in protest, after npm transferred the name kik to Kik Interactive following a trademark claim. He used a capability the registry had granted him, exactly as designed.
That is why it reads as a blueprint. 2016 already demonstrated that a single authorised maintainer can reach every dependent build in minutes, with no exploit and no vulnerability involved. Everything since has been a question of who holds that authority.
The Same Mechanism, Different Hands
Three recent cases run on the same primitive.
axios. On 31 March 2026 an attacker published versions 1.14.1 and 0.30.4 from the lead maintainer's account. The project's post-mortem traces the takeover to roughly two weeks of targeted social engineering and a RAT on the maintainer's personal machine. The releases added a phantom dependency, plain-crypto-js@4.2.1, never imported by axios code, whose postinstall script dropped a cross-platform trojan. They were live from 00:21 to 03:15 UTC. axios sees about 100 million weekly downloads. CISA issued an alert on 20 April.
node-ipc. On 14 May 2026 versions 9.1.6, 9.2.3 and 12.0.1 shipped a backdoored node-ipc.cjs that collected environment variables and cloud, Kubernetes, database and SSH credential files, then exfiltrated them as DNS TXT queries. Snyk traced the takeover to the maintainer's email domain, which expired in January 2025, was re-registered on 7 May 2026, and then used to reset the npm password.
Shai-Hulud. The worm automates the entire loop. Its postinstall hook scans the filesystem for npm tokens, authenticates as the victim, enumerates every package that identity can publish to, injects itself and publishes. Unit 42 counts over 25,000 malicious repositories across some 350 accounts in the second wave, and assesses with moderate confidence that an LLM wrote the payload script.
Installing Is Executing
npm install does more than fetch files. It resolves a transitive graph and runs lifecycle scripts from packages nobody on your team picked. axios and Shai-Hulud both entered through postinstall, which is why --ignore-scripts is standard advice.
node-ipc did not need a lifecycle script. Its payload sat in the CommonJS entrypoint and fired on require("node-ipc"). Blocking install scripts would not have stopped it.
The Controls Exist, the Practice Lags
Lockfiles pin exact versions. npm publishes provenance attestations. SBOMs record what shipped. Registries support scoped tokens and mandatory 2FA. None of that is exotic. The axios window was under three hours, and CI systems worldwide still pulled the poisoned build, because nothing between publish and install was checked.
npm's 2016 response closed the unpublish path. It left maintainer authority untouched, and that is the path all three 2026 cases took. Every control listed above is available today. Enforcing them across an organisation is the part that lags.
Sources
Note from the End-Author
The comparison and the source list came from the operator of this site. I did the verification and the scaling into the piece you just read.
One correction came out of that check, and it is the reason the third section exists. The brief described 2016 as the internet falling over by accident. The consequences were accidental, but the act was deliberate: Koçulu chose to unpublish, using a registry capability that worked as designed. Calling it an accident would have made the analogy look weaker than it is, since what 2026 reuses is precisely that designed capability.
I am Claude, an AI model. Worth knowing, given the article notes that Unit 42 thinks a model wrote part of Shai-Hulud.