11 Lines of Code Broke the Internet (left-pad)

summarized

TLDR

The left-pad incident wasn't about 11 lines of code; it was about a platform design that let one developer's protest break half the internet because npm made it trivially easy to delete dependencies. The real bug—install scripts that execute arbitrary code with zero friction—took ten years and three months to fix, and seven days later a worm was already exploiting the next unguarded default: agent configuration files that run without human review.

Key points

  • Left-pad was 11 lines, but Babel, React, Ember, and thousands of other projects broke when its author unpinned it in a trademark dispute with Kik.
  • npm restored version 0.0.3 against the author's wishes and changed the rules within a week, but the headline fix was about deletion, not execution.
  • npm install runs install scripts automatically on your machine—227 packages arrived for every 19 a developer declared, each script running with full user access.
  • September 2025: a worm stole a maintainer's tokens and backdoored 18 packages with 2.6 billion weekly downloads, rewriting crypto wallet transactions in the browser.
  • npm finally disabled install scripts by default in version 12 on July 8, 2026—ten years and three months after left-pad highlighted the problem.
  • August 4, 2026: another worm exploited a different default—agent config files that auto-run—bypassing the install-script fix entirely.
  • AI-generated vulnerability advisories are flooding the system: one account filed 55 advisories, 54 were fake, and one fake got a maximum severity score from Red Hat before being checked.
  • Modern coding agents resolve packages programmatically, removing the last human who would look at a package name and notice something off.

Tools mentioned

Techniques

  • install scripts
  • supply-chain attack via token theft
  • worm propagation via stolen maintainer tokens
  • AI-generated vulnerability advisories
  • agent config file persistence
Transcript (captions)

0:00 On a Tuesday in March 2016, a developer in Istanbul typed one command and 11 lines of code vanished. Not a framework, not a database. 11 lines that add characters to the front of a string

0:12 until it is long enough. Within minutes, Babel stopped building, then React, then Ember, then thousands of projects whose maintainers had not heard of it. NPM watched hundreds of failed installs pile

0:24 up every minute, and the number climbed with no explanation in sight. Facebook, Netflix, Spotify, and PayPal all shipped software that somewhere underneath needed those 11 lines. The package was

0:35 called left-pad. Its author had unpublished it along with 272 others he wrote. 2 and 1/2 hours later, NPM did something without precedent. It put a package back over its owner's objection.

0:48 7 days later, NPM changed the rules so a repeat was impossible. The fix worked. It is still working today. In 10 years, no deletion has taken JavaScript down again. That hole is closed, and it has

1:00 stayed closed. But last week, a worm walked through more than 400 NPM packages that get 2 billion installs a month. Same registry, same trust. So what did left-pad actually break if the

1:12 thing they fixed was not the hole? Rewind 11 days. On the 11th of March, a messaging company called Kik emailed a developer about a small NPM package that shared its name and asked him to hand it

1:24 over. They owned the trademark. He said no, and it escalated from there. So Kik went to NPM, the company that runs the registry every JavaScript project installs from. On the 18th of March,

1:35 NPM's founder Isaac Schlueter made the call. The name would go to Kik because people searching for Kik wanted the messenger. 4 days later, Azer Koçulu did the one thing the system still let him

1:45 do. He ran unpublish on everything he owned. 273 packages left the registry in a single command. He wrote that NPM was someone's private land where corporate is more powerful than the people, and

1:58 that he did open source because it gives power to the people. Whatever you make of that, it was not about the code, and the code was nothing. Left pad takes a string and sticks characters on the

2:08 front until it reaches the length you asked for. 11 lines, no dependencies. A junior developer writes it in a minute, but Babel depended on a package called line numbers, and line numbers depended

2:18 on left pad. Babel compiles most of the JavaScript on the internet. So, the moment left pad stopped resolving, every build that walked through Babel walked into a hole.

2:28 NPM's chief technology officer, Laurie Voss, put the decision in one sentence. "I cannot see hundreds of builds failing every second and not fix it." So, they broke their own rule and restored

2:38 version 0.0.3 against the wishes of its author. They called it un-unpublishing, and NPM's own postmortem is still the best account of it. A week later, the policy changed.

2:49 Today, you get 72 hours to unpublish, and after that, only if nothing in the registry depends on you, your downloads are under 300 a week, and you are the sole maintainer. That fix has held for a

3:00 decade, which is why most retellings of left pad end right here, with a tidy lesson about not depending on tiny packages. Except, the lesson is wrong. Deleting left pad was the least

3:10 dangerous thing its author could have done. If your build ran one line of code you had not approved, would you notice? Answer that before you open your lock

3:17 file, because when you type npm install, you are not downloading files, you are running code. A package can declare install scripts, and those scripts execute on your machine before your own

3:28 code runs with whatever access you had. You do not read them. At scale, you cannot. Take the project this video was rendered in. 19 dependencies in the manifest, 227 packages actually

3:40 installed, roughly 12 times more strangers than anybody picked. Russ Cox, who runs the Go language at Google, wrote the sentence that explains the next decade back in 2019. "We are

3:51 trusting more code with less justification for doing so. His example was left-pad and the habit did not go anywhere. Left-pad still carries a deprecation notice from 2018 and last

4:02 month it was downloaded 5.6 million times. More than twice the traffic it had the month it broke the internet. There is also a package called is-odd, a million downloads this week. So, the

4:13 attacker stopped deleting and started publishing. September 2025, someone fished the maintainer of chalk. 16 minutes after taking the account, 18 packages with 2.6 billion weekly

4:25 downloads between them were rewriting crypto wallet transactions in the browser. Then, the payload learned to copy itself. A worm called stole a maintainer's tokens, published

4:36 itself into that maintainer's packages, and repeated. Its second wave backdoored 796 of them. JFrog counted 177,000 new malicious packages in a year. Every one of those campaigns used the same

4:49 door. Code that runs at install time. NPM had left it open since before left-pad and closed it on the 8th of July this year. Version 12 ships with install scripts off by default.

5:01 You approve them once and the approval lands in a file a reviewer can read. Line those two dates up. The bug that made headlines was fixed in 7 days. The bug that made a decade of breaches took

5:11 10 years and 3 months. Watch what a platform makes convenient, not what its security page says it believes. 27 days later, a worm walked through the front of it anyway. The 4th of August, 2026.

5:24 Another Tuesday. A maintainer's GitHub account was taken and a poisoned release went out through a caching library called Keev. More than 400 package names, over 2,000 poison versions. Keev

5:35 alone is downloaded 156 million times a week. It stole cloud keys, registry tokens, database strings, and private keys. Then, republished itself with the tokens it had just taken. And it carried

5:47 a signature that verified the release was built by the real workflow on the real repository with NPM's trusted publishing. The attestation proved where the code was built. It was never

5:57 designed to prove the source was clean, and the source was already poisoned. And then it went somewhere NPM does not reach. It wrote its persistence into the configuration files that coding agents

6:07 read on startup, not the package, not the install script. The agents' own settings in files that auto run, that scanners were not reading, and that turning install scripts off does not

6:17 cover, which is where AI actually changes this, and not the way people usually say it. Last month, JFrog examined 55 security advisories filed by one account. 54 were fabricated. One

6:29 fake is equal light flaw got a maximum severity score from Red Hat before anyone checked whether the function it blamed existed. Affect burger, the researcher who found it, named the

6:39 asymmetry. Generative AI has lowered the effort to produce a plausible-looking advisory to close to zero, while the effort to verify one is unchanged. The backlog of unreviewed vulnerabilities

6:50 went from 17,000 to 27,000 in a year. The same asymmetry hits packages, though not the way you would guess. Models invent fewer fake package names than they used to. A study across 16 models

7:02 put the rate near 20%. The same test on five frontier models this year put it between four and six, better and not zero. Andrew Nesbit named the part that actually changed. Agents resolve

7:13 packages programmatically without a human glancing at the name to notice something is off. The last person reading the name is what gets removed. So, here is where I land. The villain is

7:23 not a developer with a grudge or a company with a trademark. It is install-time convenience. The idea that a default which saves you 10 seconds is a neutral engineering choice. For

7:33 roughly 95% of teams, the fix is unglamorous and fits on one line. Run NPM CI with install scripts off, keep the lock file pinned, and wait a day before taking a brand new version. The

7:45 rest are packages that actually compile something. Approve those once in a file somebody reviews and the concession is real. Small modules are why JavaScript shipped faster than any ecosystem in

7:55 history and I would still take a registry over vendoring every utility by hand. The argument is not against dependencies. It is against dependencies that execute, which leaves the question

8:05 the last two weeks raised. That worm's persistence did not need NPM at all. It went into the file your coding agent reads before you type anything. So when an agent installs a

8:14 package for you, who approved it and what would approved even mean if the name was read by no

Frontier News · by Hyperjump Technology