Just pasted the code into claude to try and decipher the minified js and looks like it tries to find the server via the blockchain? and then download further stuff from there.
That is 100% a compromised repo. It's a malware downloader.
I feel like they could have done a better job here. Having just a few changes, one of which is a huge blob of blatantly compromising code, is just too obvious.
The URLs are interesting, I don't do anything in this area but I didn't know that you could use the blockchains to hide your command and control URL, in a way that allows you to remotely update the URL whenever you want. It turns out there is a use for blockchain! Making control URLs immune to takedowns!
Interestingly, they added the `preinstall` key (that is supposed to run the malicious script when installed) under the package.json root, and not under `scripts`, so from what I can tell this wouldn't run on install.
Otherwise, yeah, this seems like a stage-1 loader for fetching and running a payload off the Ethereum mainnet.
He is (evidently) the product manager of NPM, so while external, I guess he should have a good idea of what's going on. Claude generated, yes, appears so, though it appears to be factually correct and fairly brief, from my quick perusal.
A very pertinent comment from zod's maintainer, from that page:
> EDIT Sept 24 — All of my packages on npm have migrated to use environment-scoped staged publishing triggerable only by workflow_dispatch. This means 2FA is always required, so even if (god forbid) an npm or GitHub token is compromised, it will not be possible for the attacker to publish new versions.
So at least that's good to see. It would be nice for them to actually remove the commit from git history, though...
> Seems like a git push credential of some kind was compromised, not an npm or GitHub token. Still working with the GitHub team to get some better forensics on what/how. The attack consisted of malicious commits and tagged pushes to main.
So it didn't go through review, it was pushed straight to main. It also seems their publishing pipeline was already secured against this sort of thing:
> Zod's release flow was already secured against kind of attack via trusted publishing and a dedicated GitHub environment for secure deployments. Zod's release CI worked as designed and was already secure against this; NPM's malware scanning didn't prevent any malicious here.
Never heard of Zod, so I went to check out the repo.
> TypeScript-first schema validation with static type inference
Who needs this? I won't even bother looking at the code since this is such a trivial problem that I couldn't imagine what you could even be implementing in there.
Just to be 100% clear, this is 100% the fault of the TS/JS ecosystem. This kind of problem literally doesn't even exist in C++/Rust because it's just.. a part of the language spec?
The solution in those languages is either to use something like serde validator, garde (for Rust), or go all the way to protobufs... or write your own data validation/parsing by hand.
Rust and C++ don't even have a Javascript deserializer.
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 release 4.6.6 on October 11, but it did NOT contain the infected code.
Btw, Zod wasn't the only package targeted - same attack was attempted against standard-schema and nub. Nub DID make it to npm, but npm's malware scanning blocked it.
Looks like a legit (well, illegitimate) attempted supply-chain attack, but no actual Zod release was compromised.
Viewed through the lens of Zod's responsibilities and processes I'd say a release was absolutely compromised. They cut and submitted a compromised release to npm; npm just happened to block the publishing.
This is not the case. Zod's release CI was not triggerable via commits/tags by design. It used environment-scoped trusted publishing, which requires a GitHub token with elevated permissions. No releases of Zod or Standard Schema were sent to npm. Their security advisory is very misleading in this regard, which is why I tried to clarify the situation in my comment. [0]
Zod maintainer here. As others have noted, no malware was shipped in any release. This was three weeks ago, and it was caught very quickly. All my git and npm credentials were immediately revoked to prevent further access. There's a security writeup from the NPM team here. [0]
It seems like the git push credential, probably an SSH key, was exfiltrated from my local computer. The attacker used this to try to push malicious versions of Zod, standard-schema, and nub. The release workflows for Zod and standard schema were already hardened against this (environment-scoped trusted publishing, which requires an npm credential), and they could not be triggered via simple commits. Nub's release CI was triggered but npm flagged the malware before it went out.
All my packages have been switched over to staged trusted publishing, which requires 2FA for any release. Since I don't know exactly what else what compromised I've also done a full OS re-install and rotated all creds present on the old machine at the time of the compromise.
Ironically this likely happened due to some work on a sandbox for Nub's package manager. The attack is consistent with a primitive older variant of a Shai-Hulud-style worm. While working on the sandbox, an ersatz agent likely executed a compromised version of some package on npm in a test run. I had safeguards against this (filtering out any OSV-flagged packages, etc) but perhaps there's an undiscovered malicious package. Future work on this work will happen on an isolated VM.
It seemed shady to scrub the commits from history, and it's wasn't clear to me that doing so is better from a security standpoint. But since there are concerns around git bisect, etc, I've done so anyway. v4.6.6 will lose provenance, v4.6.7 is being released.
53 comments
[ 0.25 ms ] story [ 53.8 ms ] threadI didn't study what packages/mini/meta.test.mjs is doing in particular but it's not looking great
Just pasted the code into claude to try and decipher the minified js and looks like it tries to find the server via the blockchain? and then download further stuff from there.
I feel like they could have done a better job here. Having just a few changes, one of which is a huge blob of blatantly compromising code, is just too obvious.
The URLs are interesting, I don't do anything in this area but I didn't know that you could use the blockchains to hide your command and control URL, in a way that allows you to remotely update the URL whenever you want. It turns out there is a use for blockchain! Making control URLs immune to takedowns!
Otherwise, yeah, this seems like a stage-1 loader for fetching and running a payload off the Ethereum mainnet.
npm 12 has the relevant breaking changes: https://github.blog/changelog/2026-06-09-upcoming-breaking-c...
Node 27 will likely ship with it:
https://github.com/nodejs/Release/issues/1161
https://github.com/npm/cli/issues/9997
https://github.com/orgs/community/discussions/208477
It definitely doesn't inspire confidence in the project taking security seriously.
(Also the "write-up" is almost surely a "Claude-up")
> EDIT Sept 24 — All of my packages on npm have migrated to use environment-scoped staged publishing triggerable only by workflow_dispatch. This means 2FA is always required, so even if (god forbid) an npm or GitHub token is compromised, it will not be possible for the attacker to publish new versions.
So at least that's good to see. It would be nice for them to actually remove the commit from git history, though...
https://github.com/colinhacks/zod/commit/10dda3a3a4bc76ed0bf...
> Seems like a git push credential of some kind was compromised, not an npm or GitHub token. Still working with the GitHub team to get some better forensics on what/how. The attack consisted of malicious commits and tagged pushes to main.
So it didn't go through review, it was pushed straight to main. It also seems their publishing pipeline was already secured against this sort of thing:
> Zod's release flow was already secured against kind of attack via trusted publishing and a dedicated GitHub environment for secure deployments. Zod's release CI worked as designed and was already secure against this; NPM's malware scanning didn't prevent any malicious here.
> TypeScript-first schema validation with static type inference
Who needs this? I won't even bother looking at the code since this is such a trivial problem that I couldn't imagine what you could even be implementing in there.
Just to be 100% clear, this is 100% the fault of the TS/JS ecosystem. This kind of problem literally doesn't even exist in C++/Rust because it's just.. a part of the language spec?
The solution in those languages is either to use something like serde validator, garde (for Rust), or go all the way to protobufs... or write your own data validation/parsing by hand.
Rust and C++ don't even have a Javascript deserializer.
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 release 4.6.6 on October 11, but it did NOT contain the infected code.
Btw, Zod wasn't the only package targeted - same attack was attempted against standard-schema and nub. Nub DID make it to npm, but npm's malware scanning blocked it.
Looks like a legit (well, illegitimate) attempted supply-chain attack, but no actual Zod release was compromised.
[0] https://github.com/orgs/community/discussions/208477#discuss...
So I think it's not a great leap to think this commit actually made it to 4.6.6 on npm.
Good that it didn't though!
Thank god. Zod reached like 350M weekly downloads recently.
name checks out
It seems like the git push credential, probably an SSH key, was exfiltrated from my local computer. The attacker used this to try to push malicious versions of Zod, standard-schema, and nub. The release workflows for Zod and standard schema were already hardened against this (environment-scoped trusted publishing, which requires an npm credential), and they could not be triggered via simple commits. Nub's release CI was triggered but npm flagged the malware before it went out.
All my packages have been switched over to staged trusted publishing, which requires 2FA for any release. Since I don't know exactly what else what compromised I've also done a full OS re-install and rotated all creds present on the old machine at the time of the compromise.
Ironically this likely happened due to some work on a sandbox for Nub's package manager. The attack is consistent with a primitive older variant of a Shai-Hulud-style worm. While working on the sandbox, an ersatz agent likely executed a compromised version of some package on npm in a test run. I had safeguards against this (filtering out any OSV-flagged packages, etc) but perhaps there's an undiscovered malicious package. Future work on this work will happen on an isolated VM.
It seemed shady to scrub the commits from history, and it's wasn't clear to me that doing so is better from a security standpoint. But since there are concerns around git bisect, etc, I've done so anyway. v4.6.6 will lose provenance, v4.6.7 is being released.
[0] https://github.com/orgs/community/discussions/208477