Security

Claude Code's 59.8 MB Source Map Leak — What It Revealed and How to Prevent It

On March 31, 2026, Anthropic accidentally shipped a 59.8 MB source map file inside their npm package. Within hours, 512,000+ lines of TypeScript were public. Here's what happened, what it exposed, and the build config that would have stopped it.

Amit Sharma
Amit SharmaSoftware Engineer, Backend Architecture at TurboDocx
April 1, 202612 min read

On March 31, 2026, Anthropic shipped version 2.1.88 of their npm package @anthropic-ai/claude-code with a 59.8 MB source map file (cli.js.map) included in the tarball. The file's sourcesContent field contained ~2,000 original TypeScript files totaling 512,000+ lines of code — the entire Claude Code codebase, unminified and readable.

The root cause was a classic packaging oversight: Bun (their bundler) generates source maps by default, and no one excluded *.map from the npm package. No .npmignore, no files field, no CI check. This guide covers what happened, what the leaked code revealed, and the four-layer build config that would have prevented it.

* This article references publicly reported information from security researchers, news outlets, and Anthropic's own statements. All sources are linked inline and listed at the end of this article.

What Happened

Claude Code is Anthropic's command-line AI coding assistant — a tool that had reportedly reached a $2.5 billion annualized run rate by early 2026. If you're new to Claude Code, our guides on writing CLAUDE.md files and shipping features in one session cover the tool in depth. It ships as an npm package (@anthropic-ai/claude-code) that developers install globally. On March 31, 2026, a routine release went out as version 2.1.88.

There was one problem: the package contained a file called cli.js.map — a 59.8 MB JavaScript source map. Source maps are debugging artifacts that map bundled code back to its original source. This particular source map contained the sourcesContent array — meaning the complete, unminified TypeScript source code of Claude Code was embedded directly in the file, available to anyone who downloaded the package.

Security researcher Chaofan Shou, an intern at Solayer Labs, discovered the exposure and posted a download link on X (formerly Twitter) at approximately 4:23 AM ET. The post accumulated over 21 million views. Within hours, the code was mirrored across GitHub and analyzed by thousands of developers.

The root cause was a classic build configuration oversight. Anthropic uses Bun (which they acquired in late 2025) as their bundler. Bun generates source maps by default during the build process. Someone on the release team failed to either disable source map generation, add *.map to .npmignore, or configure the files field in package.json to exclude debugging artifacts. Anthropic's official response was direct: “This was a release packaging issue caused by human error, not a security breach.”

Incident Timeline

Mar 31, 2026 — morning

Anthropic publishes @anthropic-ai/claude-code v2.1.88 to npm, bundled with Bun

Mar 31, 2026 — ~04:23 ET

Security researcher Chaofan Shou discovers a 59.8 MB cli.js.map file inside the package

Mar 31, 2026 — hours later

Shou posts download instructions on X (Twitter) — the post accumulates 21M+ views

Mar 31, 2026 — same day

Full TypeScript source is mirrored on GitHub; clean-room Python rewrite hits 50K stars in ~2 hours

Mar 31, 2026 — evening

Anthropic confirms: "release packaging issue caused by human error." v2.1.88 removed from npm

How Source Maps Work (and Why They're Dangerous)

A source map is a JSON file — typically ending in .map — that maps minified or bundled JavaScript back to its original source code. They exist so browser DevTools can display readable code even though the browser executes the compressed version. During development, source maps are essential. In production packages, they're a known security risk.

The critical field is sourcesContent. When present, it contains the complete original source code of every file — every comment, every internal constant, every module. No decompilation or reverse engineering needed. You just parse the JSON and read the code.

In the Claude Code leak, the cli.js.map file contained approximately 1,900 to 2,000 TypeScript source files totaling over 512,000 lines of code. The map file itself was 59.8 MB — an unusually large file for an npm package that should have raised red flags during any packaging review.

The danger is not exploitation — it's exposure

This is not a hack, not a vulnerability, not a zero-day. It is a build configuration mistake. The source map was publicly available on npm for anyone to download with npm pack @anthropic-ai/claude-code. No authentication, no exploit — just a missing line in a config file.

What the Leaked Code Revealed

The source code exposed several unreleased features and internal systems that Anthropic had not publicly disclosed. Security researchers and the open-source community quickly cataloged the key findings. Here are the most significant discoveries:

KAIROS Daemon Mode

An autonomous background agent with an "autoDream" feature — performing memory consolidation and context optimization while the user is idle.

Capybara Model Codename

Internal codename for a Claude 4.6 variant. Comments reveal Anthropic is on Capybara v8 but facing a 29-30% false claims rate (up from v4's 16.7%).

Buddy AI Pet

A Tamagotchi-style AI companion with deterministic gacha mechanics for species rarity, shiny variants, procedurally generated stats, and soul descriptions.

Anti-Distillation

An ANTI_DISTILLATION_CC flag that injects fake tool definitions into API requests — designed to pollute training data if someone records Claude Code's traffic.

Undercover Mode

An undercover.ts file implementing a mode that strips all traces of Anthropic internals when Claude Code is used in non-internal repositories.

Self-Healing Memory

A three-layer persistent memory system with automatic repair and reorganization. Designed to combat "context entropy" — AI confusion as sessions grow longer.

Competitive intelligence at scale

The leak did not expose customer data or credentials. But it exposed Anthropic's entire product roadmap, orchestration logic, and internal model performance metrics to competitors. As Penligent AI noted, the code provides “a literal blueprint for how to build high-agency, reliable, and commercially viable AI agents.”

The Community Response

The developer community's reaction was immediate and massive. The Hacker News thread alone accumulated over 1,500 comments and nearly 10 million views. Within hours, the code was being analyzed, discussed, and rewritten.

Perhaps the most remarkable development was the emergence of a clean-room Python rewrite. The power of open source was on full display as a community created a ground-up Python implementation based on Claude Code's architecture. The repository reached 50,000 GitHub stars in approximately 2 hours — what Layer5 called “likely the fastest-growing repository in GitHub history.” It eventually accumulated over 84,000 stars and 82,000 forks.

Anthropic's official response came the same day:

“Earlier today, a Claude Code release included some internal source code. No sensitive customer data or credentials were involved or exposed. This was a release packaging issue caused by human error, not a security breach.”

— Anthropic, via CNBC

Version 2.1.88 was removed from npm, and Anthropic indicated they are “rolling out measures to prevent this from happening again.” But by then, the code had been downloaded, mirrored, and analyzed by thousands. Once it's on npm, it's on the internet forever.

How to Prevent This in Your Own Packages

The Claude Code leak was preventable with any one of the following measures. The best practice is to layer all four — defense in depth means a single oversight doesn't result in exposure. If you publish npm packages — even internal ones — audit your build pipeline against this checklist. If you're looking for complementary npm security hardening, our guide on the Axios supply chain attack covers .npmrc hardening and lockfile discipline.

1Disable source maps in production builds

This is the most direct fix. If your bundler doesn't generate source maps, there's nothing to leak. Every major bundler has a flag for this — the problem is that some (like Bun) enable source maps by default, so you have to explicitly opt out.

// bun.build.ts — disable source maps for production
await Bun.build({
entrypoints: ['./src/cli.ts'],
outdir: './dist',
target: 'node',
// This is the line Anthropic missed.
// Bun generates source maps by DEFAULT.
sourcemap: 'none',
});
// Other bundlers:
// Webpack: devtool: false
// Vite: build: { sourcemap: false }
// esbuild: omit --sourcemap flag
// Rollup: output: { sourcemap: false }

2Use the package.json files field (allowlist)

The files field in package.json acts as an allowlist — only files and directories you explicitly list are included in the published package. This is the safer approach because if you forget to add something, you ship less (a missing feature, fixable). If you forget to add something to .npmignore (a denylist), you ship more (source code, credentials — catastrophic).

// package.json — allowlist approach (recommended)
{
"name": "@your-org/your-cli",
"version": "1.0.0",
"files": [
"dist/cli.js",
"dist/types/",
"README.md",
"LICENSE"
]
}
// Only these files will be included in the npm package.
// Everything else — source maps, TypeScript source,
// tests, configs — is excluded by default.

3Add .npmignore as a safety net

If your project structure makes the files allowlist impractical, use .npmignore to explicitly exclude dangerous file types. Note that .npmignore takes precedence over .gitignore for npm publishing. Even if you use the files field, having an .npmignore as a second layer of defense is good practice.

# .npmignore — denylist approach (use as backup)
# If you can't use the "files" field, exclude explicitly.
# Source maps (the cause of the Claude Code leak)
*.map
*.js.map
# TypeScript source
src/
*.ts
!*.d.ts
# Tests and configs
tests/
__tests__/
*.test.*
*.spec.*
.env
.env.*
tsconfig.json
jest.config.*

4Add a CI/CD pre-publish check

The final safety net: run npm pack --dry-run in your CI pipeline and fail the build if any .map files are detected. This catches mistakes that slip through the other layers — including the exact mistake Anthropic made. Treat npm publish like a deployment, not just a file copy.

# GitHub Actions — pre-publish source map check
- name: Verify no source maps in package
run: |
# List everything that would be published
FILES=$(npm pack --dry-run 2>&1)
echo "$FILES"
# Fail if any .map files are found
if echo "$FILES" | grep -E '\.map$'; then
echo "::error::Source map files detected in package!"
echo "Add *.map to .npmignore or remove from files field."
exit 1
fi

The core principle: allowlists over denylists

If you forget to add a file to an allowlist, you ship less — a missing feature, easy to fix with a patch release. If you forget to add a file to a denylist, you ship more — source code, credentials, internal documentation. One is a minor inconvenience. The other is the Claude Code incident.

Frequently Asked Questions

Related Resources

Build Secure Document Automation

TurboDocx helps engineering teams automate document generation with enterprise-grade security. API-first, SOC 2 compliant, and built by developers who understand the stakes.

Amit Sharma
Amit SharmaSoftware Engineer, Backend Architecture at TurboDocx