Colors.js and Faker.js Maintainer Sabotage: How Two Trusted Packages Broke Thousands of Builds Overnight
January 2022 — npm Registry. In the first two weeks of January 2022, two of the JavaScript ecosystem's most depended-upon utility packages — colors.js (roughly 20 million weekly downloads at the time) and faker.js (about 2.8 million weekly downloads) — were deliberately sabotaged by their own maintainer, Marak Squires. Within hours, CI pipelines across the industry, including infrastructure tooling like AWS's Cloud Development Kit (CDK), began failing with infinite loops and garbled console output. No CVE was assigned for weeks. No third party compromised an account, phished a credential, or slipped a payload past review. The person who broke the packages was the same person npm, GitHub, and millions of downstream developers had trusted to maintain them for over a decade.
This incident remains one of the clearest case studies in the software supply chain security field of an insider-risk class that scanning tools were never built to catch: sabotage by a legitimate, authorized maintainer. It predates the more sophisticated 2024 XZ Utils backdoor by two years, but it previewed the same underlying lesson — the trust boundary in open source is the maintainer, not just the code.
What Happened, In Sequence
Faker.js — early January 2022. Marak Squires deleted the source code of faker.js from its GitHub repository and published a broken final version to npm. Projects that pulled faker.js on install, or that used unpinned version ranges, suddenly found the package gone or replaced with a near-empty stub. Faker.js was widely used for generating mock/test data, so the breakage hit test suites and CI pipelines rather than production runtime — painful, but largely contained to build environments.
Colors.js — January 8–9, 2022. Days later, Squires pushed a new version of colors.js (published under a version string referencing "liberty") containing an intentionally destructive change: an infinite while loop combined with a function, America, that repeatedly printed zalgo-style corrupted text reading "LIBERTY LIBERTY LIBERTY" to the console. Because colors.js is a low-level terminal-coloring dependency embedded deep in the dependency trees of tools like Webpack loaders, testing frameworks, and CLI utilities, the blast radius was far larger than faker.js's. Any project that resolved to the sabotaged version at build or runtime hung indefinitely, flooding logs and consuming CI minutes. AWS CDK was among the most visible casualties, drawing widespread attention because a piece of core AWS tooling had been taken down not by an attacker, but by a two-line change from a maintainer with full, legitimate publish rights.
The motive. Squires had posted publicly in the months prior about being uncompensated for maintaining code that generates enormous value for corporations, including large cloud providers, while he received nothing. The sabotage was framed as protest rather than criminal intent — but from a supply chain risk standpoint, motive is irrelevant to blast radius. The mechanism of harm was identical to what a malicious actor would use: a legitimately-signed, legitimately-published version bump that consumers trusted by default.
The response. npm suspended Squires's account and reverted the malicious versions from the registry within days. GitHub disabled the linked repositories. Community forks — @colors/colors and community-maintained faker.js successors — sprang up almost immediately to fill the vacuum, and many organizations pinned or vendored the last known-good versions. But the reversion did not retroactively fix builds that had already resolved and cached the sabotaged versions, nor did it help teams that had no idea which of their hundreds of transitive dependencies even included colors.js.
Why This Incident Still Matters in 2026
1. It is a textbook "protestware" / insider-sabotage event, not a compromise. Traditional supply chain defenses — credential monitoring, typosquat detection, package-signing verification — are built to catch an outsider impersonating or hijacking a trusted identity. Colors.js/faker.js demonstrates a category those controls cannot address: the trusted identity itself turning hostile. Similar dynamics have recurred since, in smaller node-ipc "protestware" incidents targeting Russian and Belarusian IP ranges, and in occasional maintainer-account disputes across npm and PyPI. Any organization treating "verified publisher" as equivalent to "safe" is missing this entire risk class.
2. Transitive depth hid the exposure. Almost none of the organizations affected had colors.js or faker.js as a direct dependency. They were pulled in three, four, or five levels deep by build tooling, testing frameworks, or CLI utilities that engineering teams never audited directly. Without a dependency graph and SBOM that captures transitive relationships, most security and platform teams had no fast way to answer the only question that mattered that week: "are we exposed, and where?"
3. Version pinning and lockfiles are necessary but not sufficient. Teams with strict lockfiles and pinned versions were largely insulated from the sudden break — but only if they had pinned before the sabotaged version was published, and only if nothing in their pipeline did a floating npm install without a lockfile (common in Docker build stages, ephemeral CI runners, and "latest" tags). Auto-updating dependency bots that bumped to the sabotaged versions during the incident window turned a defensive practice into an attack vector.
4. Reachability, not presence, determines real risk. Even teams that discovered colors.js somewhere in their tree faced a second, harder question: did their actual execution path invoke the vulnerable code, or was it dead weight pulled in by a dev-only tool that never ran in production? Flat dependency inventories treat every occurrence as equally urgent, which either causes teams to panic-patch everything or, worse, causes real exposures to get lost in noise alongside cosmetic ones.
5. Detection windows matter more than post-mortems. Because this was a maintainer-initiated change rather than a flagged vulnerability, there was no advisory to subscribe to before the damage occurred. Advisory databases and CVE records lag real-world impact by days to weeks in the best case; for insider-sabotage events they often lag by design, since there's no "vulnerability" to disclose until the damage is already public. Organizations that rely solely on CVE feeds for supply chain awareness are, by construction, always reacting after the fact.
The Broader Pattern: Trust Without Verification
Colors.js and faker.js sit alongside a growing list of incidents — event-stream's cryptocurrency-wallet backdoor in 2018, ua-parser-js's account takeover in 2021, node-ipc's protestware payloads later in 2022, and the far more sophisticated XZ Utils backdoor in 2024 — that together make a single point unmistakable: the open source supply chain's trust model assumes maintainer good faith and account integrity will hold indefinitely, across every one of the hundreds of thousands of packages a typical enterprise depends on. That assumption fails periodically, sometimes through compromise and sometimes through the maintainer's own choice, and the industry has no reliable way to predict which package will be next.
What separates organizations that weathered the January 2022 breakage from those that spent days firefighting wasn't luck — it was whether they already had visibility into their full dependency graph, whether they could tell which of those dependencies were actually reachable in running code, and whether they had a fast, low-friction way to remediate once a bad version was identified.
How Safeguard Helps
Safeguard is built for exactly this failure mode: a legitimate package turning hostile with no advance warning. Our SBOM generation and ingest continuously map every direct and transitive dependency across your codebase, so when a maintainer sabotages a package — or any dependency is flagged after the fact — you get an immediate, accurate answer to "where are we exposed" instead of a multi-day dependency archaeology exercise. Reachability analysis goes a step further, distinguishing packages that are merely present in your tree from those actually invoked by code that runs in production, so your team can triage the handful of genuinely urgent exposures instead of treating every occurrence as equally critical. Griffin AI, Safeguard's security reasoning engine, continuously monitors registry and maintainer behavior signals to surface anomalous package changes — like unexplained infinite loops, deleted repositories, or sudden protest-motivated version bumps — closer to the moment they land rather than after community reports catch up. And when remediation is needed, Safeguard's auto-fix PRs generate the pinned-version or safe-replacement changes automatically, so teams can move from detection to a merged fix in minutes rather than coordinating a manual, ecosystem-wide scramble the way thousands of teams had to in January 2022.