Zod 4.6.6 pulled after malware slipped into npm release

5 min read 1 source breaking
├── "Check your lockfile, not package.json — the compromise can persist via exact-version pins even after npm's latest tag was fixed"
│  └── top10.dev editorial (top10.dev) → read below

The editorial emphasizes that the compromised 4.6.6 artifact remains resolvable by exact-version pins and lockfiles that captured it during the bad-publish window. Developers who ran install commands with caret/tilde ranges during that window should audit their lockfiles directly, since postinstall scripts or modified entry files commonly execute at install time — meaning 'I didn't import the new code' is not a safe assumption.

├── "The npm publish pipeline — not source code review — is the systemic weak point behind this wave of supply-chain attacks"
│  └── top10.dev editorial (top10.dev) → read below

Citing a pattern across ua-parser-js, event-stream, the qix chalk/debug phishing attack, and the Shai-Hulud worm, the editorial argues the vector has consistently been account or token theft rather than malicious PRs. Zod's git history appears untouched; the attack targeted the publish surface, which no amount of code-review discipline on the source repo can defend.

├── "Zod's ubiquity as a transitive dependency makes the blast radius far larger than the direct-install count suggests"
│  └── top10.dev editorial (top10.dev) → read below

The editorial argues Zod is effectively a default dependency sitting under tRPC, most modern Next.js apps doing server-side validation, API SDKs, and internal shared-types packages. That means a transitive hit on a project is more likely than a direct one, so teams who don't list Zod in their own package.json are still exposed through their dependency graph.

└── "The Zod 4.6.6 compromise is a credible, confirmed incident worth community attention"
  └── @luggage_bazooka (Hacker News, 99 pts) → view

The submitter surfaced the maintainer's own commit rolling the repo past the bad release as evidence that the compromise is real and already acknowledged upstream. The post reached 99 points with 23 comments, signaling the HN community treated it as a credible supply-chain alert rather than speculation.

What happened

Colin McDonnell (@colinhacks), maintainer of Zod — the TypeScript-first schema validation library most of the ecosystem now treats as a default dependency — pushed a commit to the repo acknowledging that version 4.6.6 on npm had been tampered with and published malicious code. The GitHub commit (`d821685`) rolls the repo state forward past the bad release, and a clean patch version was cut on npm to replace it. The compromised artifact is no longer the `latest` tag, but it is still resolvable by exact-version pins and by any lockfile that captured it during the window it was live.

If you ran `npm install`, `pnpm install`, or `yarn` against a project that resolves `zod` by caret or tilde in roughly the hours around the bad publish, your lockfile is the authoritative place to check — not your `package.json`. The usual pattern in these incidents is a `postinstall` script or a modified entry file that fires during install or on first `require`, so simply not having imported the new code is not a safe assumption if `npm install` completed on a developer or CI machine.

The mechanics of the compromise haven't been fully disclosed in the commit itself. In the recent wave of similar npm incidents — `ua-parser-js`, `event-stream`, the `qix` chalk/debug phishing attack earlier in 2025, and the Shai-Hulud worm that chewed through hundreds of packages in September — the vector has consistently been account or token theft, not a code review failure. There is no indication yet that Zod's git history was modified; the attack appears to have targeted the publish pipeline, which is the soft underbelly of npm regardless of how clean the source repo is.

Why it matters

Zod is not a long-tail dependency. It sits under tRPC, under most modern Next.js apps that do server-side validation, under a large share of API SDKs, and under enough internal "shared types" packages that a transitive hit is more likely than a direct one. The blast radius of a compromised Zod release is closer to a compromised `lodash` than to a compromised niche utility — if you have a Node project written in the last two years, there is a non-trivial chance it's in your tree.

The deeper problem is that the npm ecosystem's defenses still assume the author is the threat model. 2FA on publish is now default for high-impact packages, npm provenance via Sigstore is slowly rolling out, and GitHub's push protection catches committed secrets. None of that helps when an attacker phishes a maintainer's npm session cookie, or when a legitimately scoped CI token leaks from a GitHub Actions log. The attacker publishes under the real maintainer identity, the signature chain validates, and the package reaches millions of machines before anyone notices the diff.

The community response here has been fast — the bad version appears to have been live for a short window, and McDonnell has been transparent on the repo — but "fast" in npm-time still means tens of thousands of installs. Compare this to the Python side, where PyPI's trusted-publishers model binds publishes to specific GitHub workflow identities and makes stolen long-lived tokens largely useless. npm has the technology (provenance attestations, OIDC-based publishing) but it is still opt-in, and most popular TypeScript libraries have not adopted it.

There's also an uncomfortable second-order effect worth naming: Zod 4 is new. The 3.x → 4.x migration pulled a lot of teams onto fresh version ranges in the last few months, which means more lockfiles with recent `zod` entries and more CI pipelines pulling the latest minor. A compromise against a library mid-migration catches more hands in the cookie jar than a compromise against a mature, pinned 1.x.

What this means for your stack

First, the mechanical check. Run `npm ls zod` (or the pnpm/yarn equivalent) at the root of every project you care about. If `4.6.6` shows up anywhere in the tree — direct or transitive — treat it as a confirmed exposure on any machine where `npm install` ran against that lockfile. Grep `package-lock.json` for the exact string `"zod": "4.6.6"` and for the integrity hash of that version; the lockfile will tell you the truth your `package.json` won't.

If you find it, the response is not just "bump the version." Rotate any secret that was readable by the process that ran install — npm tokens, AWS credentials in the shell environment, SSH keys with no passphrase, `.env` files sitting in the project root. The threat model for a malicious postinstall is "read whatever the user running install can read, then exfiltrate." CI runners are the highest-priority rotation targets because they typically have the broadest ambient credentials.

Second, the structural fix. If you are not already pinning dependencies and using `npm ci` in CI with a committed lockfile, this is the hundredth reason to start. For critical dependencies — the handful of packages your product genuinely cannot function without — consider installing with `--ignore-scripts` by default and only enabling lifecycle scripts for the explicit list of packages that need them (esbuild, prisma, native-binding libraries). It is an annoying workflow for about a week and then it becomes invisible, and it neutralizes the single most common exfiltration path.

Third, provenance. When your lockfile resolver supports it, require `--foreground-scripts` and check `npm audit signatures` in CI. If a package you depend on doesn't publish with provenance yet, that's a signal to file an issue upstream rather than a reason to skip the check.

Looking ahead

The uncomfortable truth is that Zod did nothing wrong at the code level and still shipped malware to its users. Until npm makes provenance mandatory for packages above some download threshold — the way PyPI is slowly nudging its ecosystem — these incidents will keep landing on the first page of Hacker News every few weeks. The best move for individual teams is to assume the next one is already in flight, treat your lockfile as a security artifact rather than a convenience file, and make `--ignore-scripts` the default so a compromised publish buys the attacker code execution only when you say so.

Hacker News 172 pts 49 comments

Zod 4.6.6 compromised by malware?

→ read on Hacker News
yuvalkarmi · Hacker News

This is 3 weeks back, folks. It WAS real repository compromise - it made it to Zod's main, but not to npm.On September 21, someone used Colin's git credentials to push this compromised code into the project, Colin caught it, and reverted it that same day (PR #6620). He subsequently did rel

jaynetics · Hacker News

The compromised code wasn't actually released. This write-up has a lot of information:https://github.com/orgs/community/discussions/208477

luggage_bazooka · Hacker News

The most recent version 4.6.6 has a very interesting commit (d821685) "Fix bugs and improve performance", that contain the following changes https://github.com/colinhacks/zod/commit/d821685ea6732436fcd...I didn't study what packages/mini/meta.te

jaapz · Hacker News

Might is pretty tame, it is infected - EDIT: title was changed, it said "might be infected".The malware seems to inject some JS payload to execute when zod is installed, by fetching it from an ethereum smart contract (if I understand it correctly).Don't forget to flag the version on n

colinmcd · Hacker News

Zod maintainer here. As others have noted, this was three weeks ago and no malware was shipped in any release.Zod's releasing CI was never triggered and it was not vulnerable to this kind of attack. It uses environment-scoped trusted publishing, so a regular push credential is not enough to tri

// share this

// get daily digest

Top 10 dev stories every morning at 8am UTC. AI-curated. Retro terminal HTML email.