When a maintainer sabotaged colors.js and faker.js, a labour question became an operational emergency.

A domestic room at night with every light off except one glowing rectangle, shot from the doorway
An author broke his own libraries deliberately In January 2022 the maintainer of colors.js and faker.js sabotaged both, which turned a labour question into an operational one overnight.

The protest that broke builds

On 8 January 2022, Marak Squires pushed updates to two npm packages he maintained — colors.js and faker.js — that did not fix bugs or add features. colors.js began printing an infinite loop of gibberish and ANSI art to any terminal that loaded it. faker.js, a library for generating realistic fake data used heavily in test suites, was replaced at its GitHub repository with a near-empty file and a README demanding that corporations pay open-source maintainers or hire them full-time. Both packages had cumulative weekly download counts in the tens of millions. Within hours, dependent projects were broken in production.

The proximate cause was documented: Squires had been vocal for some time about the economics of open-source maintenance. He had pointed to the pattern in which large companies build revenue-generating products on freely maintained libraries while contributing nothing back — a pattern familiar enough that it had already produced manifestos, burnt-out maintainers, and intermittent funding experiments across the ecosystem. npm's dependency model, which Isaac Z. Schlueter had built to make installation trivially easy, had also made it trivially easy for thousands of companies to take a hard dependency on software one person maintained for free.

Lifted from the piece

Chronology

  1. 8 January 2022sabotaged versions of colors.js and faker.js published to npm
  2. 2016left-pad unpublish incident; npm introduces policy changes on removal
  3. 2018event-stream incident; malicious code injected via maintainer handover
  4. Post-January 2022GitHub restores faker.js repository; community forks proliferate

What the breakage revealed

The operational fallout was swift and clarifying. Projects that had pinned to exact versions — specifying a precise release number rather than a floating range — were unaffected. Projects that had trusted semantic versioning's promise of safe minor and patch upgrades, and left their package.json open enough to pull new releases automatically, pulled the sabotaged versions and broke. The distinction between "I pinned this" and "I let npm resolve this" was suddenly not an abstract engineering preference but the difference between a working build and an incident.

GitHub responded by restoring older versions of the faker.js repository from its own records. npm retained the published versions of packages on its registry under its unpublish policy — packages downloaded at scale cannot simply vanish, as the 2016 left-pad removal had already demonstrated — but it could not un-push a new version. The sabotaged releases remained reachable. The mitigation for most teams was to lock to a known-good prior version and treat any automatic upgrade as suspended until trust could be re-established.

The event-stream incident of 2018 had introduced a different threat model: malicious code injected into a package by a bad actor who had gained control of a repository. This was structurally the same mechanism — a trusted package publishing harmful changes — but the author was the original maintainer, acting openly, with a stated grievance. Nothing in npm's design distinguished between the two cases. A package you depend on can publish whatever it likes; that is what publishing means.

npm logo in white lowercase letters on a red rectangular background
A dependency became free to add and expensive to audit npm launched in 2010 and made installing someone else's code a single command. The cost moved from adding it to knowing what you had added.Photo: Npm-logo · Wikimedia Commons
Lifted from the piece

The operational stakes

  • Pinned versionlocked to an exact release; unaffected by the sabotage
  • Floating rangeallows npm to resolve newer compatible versions automatically; pulled the broken releases
  • Unpublish policynpm's rule preventing removal of packages downloaded above a threshold, established after left-pad

The question it left open

Colors.js and faker.js did not collapse the ecosystem. Pinned builds survived, forks proliferated immediately, and teams migrated quickly enough that the disruption, while real, was bounded. What the episode made permanent was a sharper awareness of what a dependency graph actually rests on: not a contract, not a service level, but the continued goodwill of whoever holds the publish keys.

The funding question Squires raised — how the labour of open-source maintenance is compensated — has no settled answer. Platforms such as GitHub Sponsors and Open Collective existed before 2022 and remain voluntary. The breakage did not produce a structural change. It produced a lesson in version pinning, a set of forks, and a clearer recognition that the arrangement most of the web's build tooling rests on is sustained by an informal agreement that can end at any time.

Empty chair facing away in a bare meeting room with half-shut blinds
A maintainer handed a popular package to a stranger The 2018 event-stream incident began with an ordinary handover of an unpaid maintenance burden, which is the part that has not been solved.