Skip to content
← Blog

Attack post-mortem

The colors and faker.js incident

3 min read

Most supply chain incidents involve malicious actors attacking from the outside. The colors.js and faker.js incident in January 2022 was different: a maintainer deliberately broke their own packages as an act of protest. It wasn't an attack in the traditional sense, but it exposed the same underlying trust vulnerability that malicious attacks exploit.

Background

colors.js is an npm package for adding color to Node.js terminal output. At the time of the incident, it was downloaded approximately 24 million times per week. faker.js provides utilities for generating fake data — names, addresses, emails — for testing. It had approximately 2.5 million weekly downloads.

Both packages were maintained by Marak Squires. He had been the primary maintainer of colors.js for over a decade.

What happened

On January 8, 2022, Squires published new versions of both packages: colors@1.4.44-liberty-2 and faker@6.6.6. The changelogs for both referenced "Liberty Liberty Liberty" — an apparent reference to political frustration.

The new versions contained code that, when executed, would print an ASCII art banner ("LIBERTY LIBERTY LIBERTY") followed by an infinite stream of nonsensical characters to stdout. Any application that imported either package would hang or produce continuous garbage output.

Within hours, thousands of automated CI pipelines that auto-updated to the latest versions failed catastrophically. The issue reports began flooding in.

Why it spread so quickly

Both packages had large downstream dependency trees. Many projects that depended on them used version ranges (^1.4.0, ~6.6.0) in their package.json instead of pinned exact versions. npm install on a fresh checkout — or a CI pipeline that didn't use npm ci — would pull in the new broken versions automatically.

Projects that used npm ci with a committed lockfile were unaffected — their lockfile pinned the previous working versions.

npm's response

npm reverted both packages to earlier versions on the registry within hours, citing a violation of npm's terms of service (the intentional sabotage of a widely-used package).

Squires had also deleted the GitHub repositories for both packages. Later, he explained that his motivation was frustration with large companies using his open-source work for free without contributing back.

What this incident reveals

The trust model of package managers is personal. When you install a package, you're trusting not just the code that exists today, but all future code that the current maintainer might publish. Packages don't get security-audited between versions. The implicit contract is: this maintainer has been trustworthy in the past and will continue to be.

The "works today, broken tomorrow" attack surface. The colors/faker incident was noisy and quickly visible. A malicious actor with the same access — a maintainer account — could cause the same kind of immediate breakage invisibly, by publishing code that exfiltrates credentials instead of printing ASCII art. The mechanism is identical.

Version ranges are a liability. Every project that used "colors": "^1.4.0" instead of "colors": "1.4.2" was vulnerable to automatic installation of the broken version. Pinned exact versions, enforced with lockfiles and npm ci, were the complete protection.

How Veln handles this class of event

Veln's signal pipeline would have caught the colors/faker versions at multiple points:

Source-pattern analysis. The broken versions introduced code with an infinite loop — a while(true) construct that was not present in any previous version. The source-pattern signals flag obfuscation, dynamic eval, and packed payloads in non-test code; a brand-new infinite loop in module-load code on a minor bump shows up as anomalous against the previously installed bytes.

Integrity fingerprint. The signed local integrity store records the file tree and hash of every previously installed (package, version). The same major version suddenly shipping a substantially different file tree raises a file-tree drift signal on the next install attempt.

Cooling gate. The version was published and could be installed immediately by projects with loose version ranges. Veln's cooling gate refuses any version younger than the configured threshold (default: 2 hours), regardless of content.

The broader lesson

The colors/faker incident is a useful reminder that supply chain security is not just about external attackers. Authorized maintainers are part of the trust surface. Veln's verification pipeline doesn't distinguish between "malicious actor who compromised an account" and "legitimate maintainer who decided to publish broken code." It treats any unexpected change — a brand-new version, a maintainer drift, a file-tree diff against the previously installed bytes — as worth examining.


Veln's cooling gate, integrity fingerprinting, and install-script pattern analysis catch intentional breakage as readily as malicious attacks.