Is Zod 4.6.6 Safe? We Unpacked the npm Tarball (2026)

On 2026-10-12 a Hacker News thread titled "Zod 4.6.6 compromised by malware?" hit 183 points. If you've got Zod in your project (and if an AI tool built your forms or API validation, you almost certainly do), that's an alarming headline.

The short answer: the zod 4.6.6 package on npm is clean. We downloaded it from the registry on 2026-10-28 and looked. The malware was real, but it lived in a GitHub commit that never got published.

TL;DR

A malicious commit landed on Zod's GitHub main branch on 2026-09-21 and added a preinstall hook that fetched remote code. It was never published to npm, because Zod's release pipeline required trusted publishing in a dedicated environment. The commit showed up in the 4.6.6 release notes, which is where the scare came from. The 4.6.6 tarball has no install script and no loader file. You only need to act if you ran an install inside a clone of the Zod repo while the commit was live (and possibly if you installed Zod as a git dependency in that window).

What actually happened

The record here is the GitHub Community discussion opened on 2026-09-21, plus the commit itself.

At 11:56:52 UTC on 2026-09-21, commit d821685 appeared on colinhacks/zod, attributed to the maintainer's account, with the harmless-sounding message "Fix bugs and improve performance." It did four things:

  • Bumped the version to 4.6.6 in both packages/zod and packages/mini.
  • Added a file called meta.test.mjs to each package, and added it to the published files list.
  • Added "preinstall": "node meta.test.mjs".
  • Changed the release workflow so a version bump on main would trigger a publish.

Despite the name, meta.test.mjs isn't a test. It makes an eth_call to an Ethereum contract to get a list of domains, fetches /loader from one of them, and runs what comes back. Errors are swallowed. Looking the server up on-chain means there's no domain in the code to block, and the actual payload never appears in the diff.

Then it hit a wall. In the maintainer's words, Zod's release CI "worked as designed." Publishing needed trusted publishing from a dedicated, protected environment, and a pushed commit couldn't satisfy that. The attacker got a commit in, but couldn't turn it into a release.

The same morning, similar loader commits went into standard-schema (12:37 UTC) and nub (12:54 and 13:00 UTC). standard-schema's commit never reached npm. nub's did reach npm publishing, where npm's publish-time scanning blocked @nubjs/nub@0.9.4 at 13:09 UTC. The maintainer called that detection "a BIG win."

On how the attacker got in, Colin McDonnell wrote: "Seems like a git push credential of some kind was compromised, not an npm or GitHub token." He said forensics with GitHub were still in progress, and nothing public since has confirmed more.

Why 4.6.6 took the blame

The real 4.6.6 was published to npm on 2026-10-11 at 16:18 UTC, three weeks after the attack. Its GitHub release notes listed the commits since the last release, and the malicious commit (followed by its revert) was in that range. Anyone reading the notes saw "4.6.6" and a malware commit in the same place and drew the obvious conclusion. 4.6.7 followed on 2026-10-12, after the maintainer cleaned up the repo history.

That's the whole story behind the headline. A version number in a commit message, a changelog that lists commits, and a published package are three different things.

What we checked

We pulled the published tarball straight from the registry and unpacked it:

Terminal
npm view zod@4.6.6 scripts
curl -sO https://registry.npmjs.org/zod/-/zod-4.6.6.tgz
tar -xzf zod-4.6.6.tgz
ls package/meta.test.mjs     # No such file or directory

Results, as of 2026-10-28:

Checkzod 4.6.6 on npm
meta.test.mjs presentNo
preinstall / install / postinstall scriptNone
Scripts in package.jsontest, build, clean, postbuild, test:watch, prepublishOnly (all developer scripts that npm doesn't run on install)
Provenance attestation in registry metadataPresent

One loose end, in fairness. In the discussion, the maintainer wrote that after the history cleanup "v4.6.6 loses npm provenance." The registry record we pulled on 2026-10-28 still lists an attestation for 4.6.6. We can't reconcile those two, and it doesn't change the contents of the tarball. If it bothers you, 4.6.7 sidesteps the question.

Do you need to do anything?

For almost everyone: no. Run this to see where your Zod came from:

Terminal
npm ls zod
grep -nE 'zod@|"zod"|colinhacks/zod' package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null
ls node_modules/zod/meta.test.mjs 2>/dev/null && echo "INVESTIGATE"

You're fine if the lockfile shows Zod resolved from registry.npmjs.org (that's the normal case) and there's no meta.test.mjs in node_modules/zod.

You should treat the machine as possibly compromised if either of these is true:

  • You cloned the Zod repo itself and ran an install while the commit was on main. The hook sat in the repo's workspace packages, so this is the confirmed route.
  • Your package.json pulls Zod from GitHub ("zod": "github:colinhacks/zod" or a git+https:// URL) and you installed between 11:56 UTC on 2026-09-21 and the revert. We haven't verified that a git dependency would run that hook, but don't bet a machine on it.

In that case, the preinstall hook could have run and fetched remote code. Rotate the credentials that machine could reach (npm and GitHub tokens, cloud keys, the API keys in your .env files) and see our npm supply chain checklist for the full response.

The useful lesson here

The scare spread because it's genuinely hard to tell "this repo had a bad commit" from "this package is infected." Two habits make it easy:

Check the package, not the headline. npm view <pkg>@<version> scripts shows whether a version runs anything on install. This payload needed an install hook to run. The published version didn't have it.

Install with scripts off by default. npm config set ignore-scripts true (or pnpm 10+, which doesn't run dependency build scripts unless you approve them) would have stopped this exact payload even if it had been published. It won't stop everything: our supply chain guide covers a 2026 compromise that ran without an install script. But it closes the most common door.

Zod's maintainer also said his packages now publish through an environment-scoped, staged process triggered only by workflow_dispatch with 2FA. That's the same lesson from the other side: a stolen push credential should never be enough to ship a release.

Is zod 4.6.6 from npm infected?

No. We downloaded the zod 4.6.6 tarball from the npm registry on 2026-10-28. It contains no meta.test.mjs and no preinstall, install or postinstall script. The malicious code was in a GitHub commit that Zod's release pipeline never published.

Should I upgrade to zod 4.6.7 anyway?

It doesn't hurt, and it's the version the maintainer published after cleaning up the repo history. But you don't need to treat 4.6.6 as an emergency if it came from the npm registry.

Who should actually worry?

Mainly anyone who cloned the Zod repository and ran an install while the malicious commit was on main after 11:56 UTC on 2026-09-21, since the hook sat in the workspace packages. Installing Zod as a git dependency (github:colinhacks/zod) in that window is a possible route too, though we haven't verified it would run the hook. Either way, treat that machine as possibly compromised.

How did the attacker get in?

The maintainer wrote that a git push credential of some kind was compromised, not an npm or GitHub token, and that forensics with GitHub were ongoing. Zod's release CI used trusted publishing and a dedicated environment, which is why the commit never became an npm release.

Were other packages hit?

The same discussion lists similar loader commits to standard-schema and nub that morning. standard-schema never reached npm. The nub release did reach npm publishing, where npm's own scanning blocked @nubjs/nub 0.9.4 at 13:09 UTC on 2026-09-21.

Check what your app actually exposes

Supply chain scares come and go. CheckYourVibe scans your live app for the leaks attackers use every day: keys in the bundle, open configs, missing headers.

Vulnerability Guides

Is Zod 4.6.6 Safe? We Unpacked the npm Tarball (2026)