Supply Chain Attack on @ctrl/tinycolor: What We Can Learn

Just analyzed a fascinating supply chain attack that hit the npm ecosystem. The @ctrl/tinycolor package (2M weekly downloads) got compromised through a shared GitHub repo exploit - no direct account compromise or phishing involved.

What Happened

The attacker gained admin rights in a shared repository (angulartics2) and pushed a malicious GitHub Actions workflow that stole an npm token with broad publish rights. They then published malicious versions of 20 packages, including @ctrl/tinycolor.

The Scary Part

This wasn’t your typical “developer got phished” scenario. It was a sophisticated exploit of collaborative repository management. The malicious versions would trigger postinstall payloads if installed.

Immediate Takeaways

  1. Granular npm tokens - Stop using tokens with broad publish rights
  2. pnpm > npm - Package managers that prevent unapproved postinstall scripts
  3. Trusted Publishing (OIDC) - Eliminate static tokens entirely
  4. Stricter access controls - Not everyone needs admin rights

Anyone else been auditing their npm dependencies lately? This feels like a wake-up call for the entire ecosystem.

Great responses everyone! A few follow-ups:

@devops_dan Trusted Publishing is solid once you get through the initial setup. The OIDC flow eliminates the token management headache entirely. We migrated 15 packages last quarter - main gotcha is making sure your workflow permissions are locked down.

@frontend_felix Your automation list looks good. I’d add npm-audit-ci for breaking builds on high-severity vulns. Also consider using npm ci instead of npm install in production - it’s stricter about lockfile consistency.

@backend_betty Sigstore wouldn’t have helped here since the attacker had legitimate publish rights. But it’s great for verifying authentic packages in general. The real fix is better access controls and token hygiene.

The bigger picture

This attack worked because of excessive permissions in collaborative environments. It’s not just npm - we’re seeing similar patterns in:

  • Docker Hub organizations
  • PyPI package maintenance
  • GitHub marketplace apps

Time to audit everything, not just npm tokens.

This is why I switched to Bun. Their package resolution is way more secure by default. Also using lockfiles religiously now - bun install --frozen-lockfile in CI catches these issues early.

Data science packages are even worse - lots of unmaintained Python packages with similar attack vectors. We’re now pinning everything in requirements.txt and using pip-audit.