npm's Worst Day: One Attack, One Leak, Zero Trust
Ricardo Argüello — March 31, 2026
CEO & Founder
General summary
On March 31, 2026, npm broke twice. First, an attacker hijacked the axios maintainer's account and published versions that deployed a cross-platform RAT to anyone who ran npm install. Hours later, a researcher discovered that Anthropic had accidentally published Claude Code's entire source code — 512,000+ lines of TypeScript — via a source map file left in the npm package. One was malice. The other was negligence. Your defenses for one don't protect against the other.
- An attacker hijacked the axios npm account and published versions with a phantom dependency that deployed a cross-platform RAT targeting macOS, Windows, and Linux
- Socket.dev flagged the malicious package within 6 minutes, but the compromised versions were live for 2-3 hours — observed execution in 3% of affected environments
- Separately, researcher Chaofan Shou discovered Anthropic published Claude Code's complete source code (1,900 files, 512K+ lines) via a source map left in the npm package
- The Claude Code leak exposed system prompts, hidden features (KAIROS, Capybara models), and a Tamagotchi-style AI pet — marking Anthropic's 4th operational incident in 6 weeks
- Both incidents hit the same registry on the same day but require completely different defenses: credential security vs. build pipeline hygiene
Imagine two neighbors on the same street. One gets robbed because someone picked the lock. The other leaves their blueprints on the front lawn because they forgot to close the garage door. The street is npm. The robber is the axios attacker. The open garage is Anthropic's build pipeline. Both homes are compromised — but the lock company can't fix the garage door, and the garage door company can't stop a lockpick.
AI-generated summary
On March 31, 2026, someone hijacked the axios maintainer’s npm account and published versions that deployed a remote access trojan to anyone who ran npm install. Axios has ~100 million weekly downloads and sits in ~80% of cloud environments.
Hours later — completely unrelated — a researcher discovered that Anthropic had published Claude Code’s entire source code, 512,000+ lines of TypeScript, because a source map file was left in the npm package.
I don’t usually cover two unrelated incidents in the same post, but these two share something that matters: they’re different kinds of broken, and fixing one wouldn’t have helped with the other.
The axios attack
Around midnight UTC on March 31, Feross Aboukhadijeh from Socket.dev sounded the alarm: axios@1.14.1 had pulled in plain-crypto-js@4.2.1, a package that didn’t exist before that day. Thirty-nine minutes later, axios@0.30.4 followed — the attacker poisoned both the 1.x and 0.x branches to maximize blast radius.
What happened next was surprisingly straightforward. The attacker hijacked the jasonsaayman account — axios’s lead maintainer — changed the email to a Proton Mail address, and published both versions manually via npm CLI. Not through GitHub Actions, not through the project’s normal release pipeline. Straight to the registry. The malicious dependency never showed up in the GitHub repository at all.
plain-crypto-js did one thing: execute a postinstall script that deployed a cross-platform RAT.
| Platform | Payload | Disguise |
|---|---|---|
| macOS | Binary at /Library/Caches/com.apple.act.mond | Apple system daemon |
| Windows | PowerShell copy at %PROGRAMDATA%\wt.exe | Windows Terminal |
| Linux | Python script at /tmp/ld.py | Temporary file |
The dropper used dual-layer encoding — reversed Base64 plus XOR cipher — to evade static analysis. After execution, it self-destructed: deleted setup.js, replaced the malicious package.json with a clean stub showing version 4.2.0. Post-execution, npm list showed nothing suspicious.
Socket.dev’s automated scanner flagged plain-crypto-js within 6 minutes of publication. npm removed the malicious versions within ~3 hours. But in that window, 3% of affected environments had already executed the payload.
If you installed axios between roughly 00:21 and 03:15 UTC on March 31 and got the affected versions, treat your system as fully compromised. Rotate every credential on that machine.
Claude Code’s 512,000-line leak
Hours later, security researcher Chaofan Shou published a finding that had nothing to do with the axios attack but everything to do with npm.
Anthropic’s Claude Code CLI — version 2.1.88 — shipped with a 57 MB source map file that mapped the minified production bundle back to the original TypeScript source. Anyone who ran npm pack or browsed the package contents could read Anthropic’s entire codebase in plain text.
The scale: ~1,900 files, 512,000+ lines of TypeScript, ~40 built-in tools, ~50 slash commands. The core query engine alone was 46,000 lines. The tool definition system was 29,000 lines.
I spent an hour reading through the leaked code. The architecture itself is well-organized TypeScript — nothing scandalous there. What drew my attention was everything else that came along with it.
All of Claude Code’s system prompts — the full instructions that govern how it behaves — were sitting in a JSON file that npm serves to anyone who asks. The Hacker News thread flagged a regex-based system for detecting negative sentiment and profanity in user prompts, which gets logged. That got people talking about what else the telemetry captures.
Then there were the unreleased features. KAIROS is a persistent, always-running assistant mode that watches, logs, and proactively acts on things it notices — gated behind compile-time flags and absent from public builds. A “Capybara” model family showed up in the code, confirming the codename from the Mythos leak three days earlier. And a /buddy command activates a Tamagotchi-style AI pet with species, rarity tiers, stats, and animations.
The one that generated the most debate was an “undercover mode” that strips AI-identifying information from commits. Some saw it as practical tooling; others called it problematic AI impersonation.
How did it happen? Claude Code uses Bun’s bundler, which generates source maps by default unless you explicitly turn them off. Someone forgot to add *.map to .npmignore or configure the bundler to skip source map generation for production builds. According to CyberSecurity News, this is the second similar source map exposure from Anthropic — a comparable incident occurred in early 2025.
No user data was compromised. No malware was involved. But Anthropic’s complete tool architecture, permission system, authentication flows, and unreleased product roadmap are now public.
What connects these two incidents — and what doesn’t
When I sat down to write about the axios attack, I realized I couldn’t ignore the Claude Code leak happening on the same day. Not because the incidents are related — they’re not. But after 20+ years reviewing software infrastructure — and now doing it at IQ Source for B2B clients across Latin America — I keep finding the same thing: teams prepare for one kind of problem and leave the other wide open.
The axios attack is a credential problem. Long-lived npm token, no MFA enforced, no provenance checks. Socket.dev’s automated scanner caught it in 6 minutes — the tooling exists. The fix lives with the security team.
The Claude Code leak is a pipeline problem. Source maps left in the package, no .npmignore, nobody ever ran npm pack --dry-run. No automated scanner flagged it — an external researcher browsing npm found it by accident. The fix lives with DevOps.
The teams responsible don’t even overlap. Authentication hardening is the security team’s job. Build artifact auditing is DevOps. In most organizations, those teams don’t talk to each other about npm — and npm doesn’t distinguish between the threats either. It’s just a registry, serving packages regardless of whether they were compromised by an attacker or bloated by a forgotten debug file.
AI agents made it worse
Andrej Karpathy posted about his near-miss within hours. He had installed @googleworkspace/cli a few days earlier, which pulled axios 1.13.5 — one version before the poisoned release. If he’d installed it a few hours later, the unpinned dependency would have resolved to the compromised version.
His observation was the one that stuck: “I can’t feel like I’m playing russian roulette with each pip install or npm install (which LLMs also run liberally on my behalf).”
That phrase — “which LLMs also run liberally on my behalf” — deserves its own section. Six days ago, we wrote about how the LiteLLM attack broke AI trust chains at the dependency level. But the LiteLLM post didn’t cover what happens when AI coding agents run npm install on their own. No diff review. Resolve to latest by default. At 3 AM while you sleep.
Multiple replies in Karpathy’s thread named the exact scenario — “agentic flows that auto-install deps without pinning are the worst case. Compromised at machine speed with no one checking the diff.” The risk isn’t just that your dependency chain has weak links. It’s that AI tooling is now accelerating through those weak links faster than any human can review.
What actually prevents this
Dependency pinning alone wouldn’t have prevented either breach. The specific controls that would have actually stopped them are different for each case:
Against the axios attack
pnpm’s default security model. pnpm disables postinstall scripts by default for all packages except explicitly allowlisted ones. If the affected environments had used pnpm instead of npm, the RAT dropper would never have executed — even with the compromised version installed.
SLSA provenance. The malicious versions had no provenance record because they were published manually via CLI, not through the project’s normal GitHub Actions pipeline. If npm enforced provenance checks for popular packages, the unsigned versions would have been rejected at install time.
Minimum release-age constraints. A policy that rejects packages published within the last 72 hours would have given the community time to analyze before anyone installed. socket.dev already offers this in their Socket Firewall.
Against the Claude Code leak
npm pack --dry-run before every publish. One command that shows you exactly what files will be included in the package. If anyone at Anthropic had run this before publishing 2.1.88, the 57 MB source map file would have been immediately visible.
Explicit .npmignore. Add *.map, *.map.js, and any debug artifact to .npmignore. Don’t rely on .gitignore — npm uses .npmignore if it exists and falls back to .gitignore if it doesn’t.
Bundler configuration. Bun generates source maps by default. For production builds, set sourcemap: "none" explicitly. Don’t leave defaults for production artifacts.
CI/CD publish verification. A pre-publish step that checks total package size and flags unexpected files. A 57 MB source map in a CLI tool package should have triggered an alert before it reached the registry.
Anthropic’s fourth incident in six weeks
We use Claude every day at IQ Source and build client solutions with it. That doesn’t change what four incidents in six weeks tells you about operational maturity — and if you’re evaluating AI vendors, this pattern should be on your radar.
In six weeks: Mrinank Sharma resigned citing internal governance concerns. Anthropic dropped its pause commitment from the Responsible Scaling Policy. The Mythos leak exposed ~3,000 internal documents via a CMS misconfiguration. And now Claude Code’s full source code published to npm via a build configuration error.
We covered the vendor trust implications in detail three days ago, and I stand by that analysis. Today just added a fourth data point. If your vendor evaluation framework still focuses on model benchmarks and certifications without looking at the vendor’s operational track record, you’re missing the pattern.
What we changed at IQ Source after this
We ran npm pack --dry-run on every package we maintain before noon on March 31. No source maps, no .env files, no surprises. That took 15 minutes. It should have already been part of our CI — now it is.
Then we audited lockfiles for every active client project. We looked for three things: packages with postinstall scripts we hadn’t reviewed, unpinned caret-range dependencies on high-download packages, and CI pipelines that resolve latest instead of installing from a lockfile.
The first check is about what you consume. The second is about what you ship. If you only do one, March 31 showed what happens with the other.
I keep coming back to something Karpathy wrote in a reply on that thread: “I can’t feel like I’m playing russian roulette with each npm install.” If your team feels the same way — or if you’ve got AI agents doing the installing for you — send us your package-lock.json at contact. We’ll tell you which side of March 31 you’re exposed on.
Frequently Asked Questions
An attacker hijacked the npm account of axios's lead maintainer and published versions 1.14.1 and 0.30.4 containing a phantom dependency called plain-crypto-js. That dependency deployed a cross-platform RAT via a postinstall script. Axios has ~100 million weekly downloads. The malicious versions were live for 2-3 hours before npm removed them. Advisory: GHSA-fw8c-xr5c-95f9.
Claude Code version 2.1.88 shipped with a 57 MB source map file that mapped the minified bundle back to the original TypeScript. Source maps are debugging artifacts that should never ship in production packages. Bun's bundler generates them by default. Anthropic forgot to exclude them from the npm publish, exposing 1,900 files and 512,000+ lines of code.
The leak revealed KAIROS, a persistent always-running assistant mode gated behind feature flags; references to a 'Capybara' model family confirming the codename from the Mythos leak; a Tamagotchi-style AI pet system accessible via a /buddy command; an undercover mode that strips AI attribution from commits; and user frustration detection via sentiment analysis regex.
For supply chain attacks: use pnpm (blocks postinstall by default), pin exact versions, verify SLSA provenance, and set minimum release-age constraints. For source map leaks: run npm pack --dry-run before every publish, add *.map to .npmignore, and audit build output. Neither defense covers both failure modes — you need both.
Related Articles
Your Code Review Was Built for Humans. 41% of Code Isn't
41% of code shipped in 2025 was AI-generated, with a 1.7x higher defect rate. Your review process assumes the author understands the code. That's over.
What Your AI Won't Ask (and Your Startup Will Pay)
A founder lost $87,500 because his AI generated working code without questioning security. AI tools answer what you ask, not what's missing.