惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
D
DataBreaches.Net
GbyAI
GbyAI
Microsoft Security Blog
Microsoft Security Blog
博客园_首页
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
IT之家
IT之家
MongoDB | Blog
MongoDB | Blog
The GitHub Blog
The GitHub Blog
月光博客
月光博客
U
Unit 42
Hugging Face - Blog
Hugging Face - Blog
博客园 - 叶小钗
腾讯CDC
B
Blog RSS Feed
博客园 - Franky
爱范儿
爱范儿

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Three npm Disasters That Were Predictable (And What the S...
Pico · 2026-04-30 · via DEV Community

Supply chain attacks don't come from nowhere. They exploit structural conditions that existed long before the incident — single maintainers, token concentration, asymmetric blast radius. The conditions are visible. The question is whether anyone is looking.

We took three of the most consequential npm supply chain attacks in the last eight years and analyzed each one through proof-of-commitment — behavioral scoring that measures structural resilience, not CVE databases. For each incident, we ran the actual package through the API today, then reconstructed what the signals would have shown before the attack.

The results are honest. In some cases, the tool would have flagged the exact vulnerability exploited. In others, the signal was there but below the alarm threshold. We'll show both.


Case 1: event-stream (2018)

What happened

In November 2018, a developer named right9ctrl approached Dominic Tarr, the sole maintainer of event-stream, and offered to take over maintenance of the package. Tarr, who had moved on from the project, agreed. The new maintainer added a dependency called flatmap-stream, which contained an encrypted payload targeting Copay — a Bitcoin wallet — to steal cryptocurrency. The attack went undetected for two months. It targeted a specific downstream package while hiding in a generic utility with ~2 million weekly downloads at the time.

What proof-of-commitment sees today

Package Score Risk Maintainers Downloads/wk Age
event-stream 67 ⚠️ WARN 1 6.0M 14.7 yrs

Score: 67 — sitting in the "GOOD" band but well below the "HEALTHY" threshold of 75. The WARN flag fires because of single-maintainer risk. It misses CRITICAL only because downloads are under 10 million per week.

What signals existed before the attack

  • Single maintainer — Dominic Tarr was the only person with npm publish access. When he handed the keys over, there was no governance process, no second pair of eyes, no institutional memory.
  • Maintainer handoff pattern — A new, unknown contributor took ownership. This is the single strongest behavioral signal for social engineering attacks, and it's the one thing nobody was monitoring.
  • Sudden new dependency — The addition of flatmap-stream, a brand-new package with no download history, should have been a structural anomaly. An established package suddenly depending on an unknown package is a pattern, not just a diff.
  • Abandoned project, active downloads — Tarr had publicly stated he was no longer interested in maintaining the package. An abandoned but highly-downloaded package is the ideal target for social engineering.

Verdict: partially

Proof-of-commitment would have flagged the single-maintainer risk — that was the structural condition that made the social engineering attack possible. But it would not have specifically detected the maintainer handoff or the suspicious new dependency.

What it does prove: the structural condition that enabled the attack was observable. One maintainer. No governance. High download count relative to maintainer investment.


Case 2: ua-parser-js (2021)

What happened

In October 2021, the npm account of Faisal Salman — the sole maintainer of ua-parser-js — was compromised. The attacker published three malicious versions that contained a cryptominer and a credential-stealing trojan targeting Linux and Windows systems. The package had approximately 7 million weekly downloads at the time and was used by companies including Facebook, Microsoft, Amazon, and Google. The malicious versions were live for roughly four hours before removal.

What proof-of-commitment sees today

Package Score Risk Maintainers Downloads/wk Age
ua-parser-js 83 🔴 CRITICAL 1 25.4M 13.7 yrs

Today: score 83, single maintainer, 25.4 million weekly downloads. CRITICAL. The exact profile that was exploited.

What signals existed before the attack

  • Single maintainer with sole npm token — Faisal Salman was the only person who could publish. One compromised credential = full access to 7 million weekly installs.
  • High download-to-maintainer ratio — Even at 7M weekly downloads, the ratio of "people who depend on this" to "people who can publish" was approximately 7,000,000 : 1.
  • npm didn't require 2FA at the time — A single password could, and did, compromise the entire package.
  • Behavioral score looks fine — This is the uncomfortable part. The package was well-maintained, consistently released, widely adopted. Every quality metric was positive. The vulnerability was invisible to quality analysis.

Verdict: yes

Proof-of-commitment would have flagged this. In 2021, with ~7M weekly downloads, it would have been right at the CRITICAL boundary — WARN at minimum, with the single-maintainer flag clearly visible.

Three years after the attack, nothing has structurally changed. ua-parser-js today still has one maintainer. Downloads have grown from 7M to 25M per week. The blast radius is 3.6x larger than when it was compromised. The same attack would work again, with more damage.


Case 3: colors.js (January 2022)

What happened

In January 2022, Marak Squiress — the sole maintainer of colors.js and faker.js — intentionally published breaking versions of both packages. colors.js v1.4.44 and v1.4.45 introduced an infinite loop that caused any application importing the package to hang indefinitely. The package had approximately 35 million weekly downloads. Hundreds of open source projects and enterprise CI/CD pipelines broke immediately.

Marak had been publicly protesting the fact that large corporations were building commercial products on his unpaid open source work. The sabotage was intentional and announced. The entire incident was enabled by a single structural condition: he was the only person who could publish these packages.

What proof-of-commitment sees today

Package Score Risk Maintainers Downloads/wk Age
colors 65 🔴 CRITICAL 1 19.8M 15.1 yrs

Today: score 65, single maintainer, 19.8 million weekly downloads — and still CRITICAL. The download count has declined from ~35M since the incident damaged ecosystem trust, but the structural profile is unchanged. One person. One token. Millions of installs.

What signals existed before the incident

  • CRITICAL flag was present — At ~35M weekly downloads and sole maintainer, colors.js would have been flagged CRITICAL.
  • High score provided false comfort — colors.js was a well-maintained package with 15 years of history, consistent releases, and stable download trends. Every quality metric was positive. The risk wasn't about quality — it was about governance.
  • No governance structure — There was no second reviewer, no multi-maintainer quorum, no npm organizational account. The entire blast radius rested on one person's continued good will.
  • The signal is broader than external attacks — This case proves that CRITICAL flagging isn't only about token compromise. It's about any failure mode of the sole maintainer: burnout, grievance, instability, or compromise.

Verdict: yes, clearly

The CRITICAL flag is explicitly designed for this scenario. Not just external attacks — any failure of the single person at the helm.

npm audit showed nothing before the incident — there were no known vulnerabilities. CVE databases showed nothing. Every toolchain in the ecosystem reported green until the packages broke. The structural flag would have shown red for months.


Summary

Incident Attack vector npm audit CVE PoC flag Would PoC have helped?
event-stream (2018) Social engineering ⚠️ WARN Partially — flagged single maintainer, but wouldn't detect handoff
ua-parser-js (2021) Token compromise ⚠️ WARN* Yes — exact vulnerability flagged. *WARN at 2021 volume, CRITICAL today
colors.js (2022) Intentional sabotage 🔴 CRITICAL Yes — sole-maintainer flag visible for entire 15-year package history

The pattern across all three: zero pre-incident warnings from existing tools. npm audit looks at known CVEs — it can't flag structural risk. CVE databases are reactive by design — they catalog what already happened. Neither tool measures the conditions that make attacks viable.


What We Can't Catch (Yet)

  • Maintainer handoffs — The event-stream attack exploited a change in who controls the package. The current scoring is point-in-time; it doesn't track behavioral diffs over time. This is the most important gap.
  • New dependency injection — The addition of flatmap-stream was a structural anomaly. Detecting sudden new dependencies in established packages would catch this class of attack. Not implemented yet.
  • Code-level malice — The tool measures structural governance, not code content. If a trusted maintainer ships malicious code, the structural score won't reflect it. Deliberate scope boundary — structural governance and code analysis are different problems.

What it does catch: the structural conditions that make these attacks possible and high-impact. Single maintainer. Token concentration. Asymmetric blast radius. These conditions precede every attack in this analysis by months or years.


Try It

Run any package through proof-of-commitment in 10 seconds:

npx proof-of-commitment axios ua-parser-js event-stream
# Or your whole project:
npx proof-of-commitment --file package.json
# Or lock files — scans ALL transitive deps:
npx proof-of-commitment --file package-lock.json

Enter fullscreen mode Exit fullscreen mode

Web interface: getcommit.dev/audit

GitHub Action (posts risk table on PRs):

- uses: piiiico/proof-of-commitment@main
  with:
    fail-on-critical: false
    comment-on-pr: true

Enter fullscreen mode Exit fullscreen mode

MCP server for Claude Desktop, Cursor, or Windsurf:

{
  "mcpServers": {
    "proof-of-commitment": {
      "type": "streamable-http",
      "url": "https://poc-backend.amdal-dev.workers.dev/mcp"
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

All data sourced from public npm registry and GitHub APIs. Open source: github.com/piiiico/proof-of-commitment. MIT licensed.


We're building Commit — trust infrastructure for the autonomous economy. Behavioral commitment data, not declarations.

Related: State of npm Trust: April 2026 · The axios signal