What is a source map leak?
Source maps map minified output back to readable source. Your bundler generates them. Your .npmignore is supposed to exclude them. When it does not, the full source ships inside the published package. Internal architecture, feature flags, unreleased product names. All readable by anyone who runs npm install.
A source map leak is when an app accidentally ships its actual source code inside a download that anyone can grab. Source maps are special files that connect the scrambled production code back to the original readable version. They help with debugging but should never be published. When they slip into a public release, anyone can read the full source code, including internal settings, hidden features, and product plans that were not meant to be public. If you build with Claude Code, Cursor, or a similar AI tool, your AI assistant could pull in a leaked source map without you realizing what it contains.
Source maps are build artifacts. Bundlers like Bun, Webpack, and esbuild generate them to map minified output back to readable source. They exist for debugging. They are not meant to ship.
When a packaging pipeline fails to exclude them, the full source crosses the trust boundary inside the published artifact. Internal architecture, feature flags, model codenames, agent orchestration patterns, unreleased capability references. All readable by anyone who runs npm install.
The numbers
March 31, 2026. Anthropic publishes @anthropic-ai/claude-code@2.1.88 to npm. The tarball contains a 59.8 MB source map: 512,000+ lines of TypeScript across 1,906 files. A researcher flags it in 23 minutes. 41,000 GitHub forks within an hour. Anthropic yanks the version. The bytes are already cached across every CI pipeline and package mirror that pulled it.
This was the second time in 13 months. Same category of mistake. Same file type. Different version.
On March 31, 2026, Anthropic released an update to Claude Code. Inside the download was a 59.8 MB file containing over 512,000 lines of their internal source code.
A security researcher found it within 23 minutes. Within an hour, 41,000 people had copied it. Anthropic pulled the update. By then, it was everywhere.
This was the second time in 13 months. Same kind of mistake. Same type of file.
March 31, 2026. Anthropic ships Claude Code v2.1.88 to npm. The artifact contains the full TypeScript source: 1,906 files, 59.8 MB. A researcher flags it in 23 minutes. Within an hour, 41,000 forks on GitHub. Anthropic pulls the version. The artifact is already cached across CI pipelines, package mirrors, and archive services worldwide.
This was the second time in 13 months. Same failure category. Same artifact type. The recurrence was deterministic.
What happened
Bun emits source maps by default. development: false does not suppress them. This is documented behavior, not a bug.
.npmignore is the last gate before your code hits the public registry. Anthropic's did not have a *.map entry. So npm publish shipped the source map.
Two config surfaces with zero awareness of each other. The bundler produces files. The publish filter does not know what the bundler produced.
Boris Cherny, head of Claude Code engineering, called it a "plain developer error." He was right. Here is the fix:
# .npmignore
*.map
*.ts
!*.d.ts
src/
tests/
One line. Five characters. That is the entire fix.
The root cause was a gap between two tools that do not talk to each other.
Boris Cherny, head of Claude Code engineering, called it a "plain developer error." He was right. The fix was adding one line to one config file. Five characters.
Two config surfaces. Zero cross-validation between them.
development: false does not suppress maps. This is not a bug..npmignore missing *.mapBoris Cherny, head of Claude Code engineering, called it a "plain developer error." He was right. Five characters in .npmignore would have stopped it. The interesting question is not why the line was missing. It is why nothing in the pipeline checked.
What leaked
Not model weights. Not customer data. Not API keys. What shipped was the full TypeScript source: internal feature flags, model codenames, unreleased product references, and the complete tool-use orchestration architecture.
We are not listing specifics. That is Anthropic's IP.
The damage was competitive, not operational. Anyone who downloaded the package could read the engineering patterns, architecture decisions, and product roadmap. Not from a breach. Not from a compromised insider. From a .npmignore that was missing five characters.
The leaked file contained the full source code of Claude Code. Not the AI model itself. Not customer data. Not passwords. But it did contain internal feature names, references to unreleased products, and the full engineering blueprint of how Claude Code works.
We are not going to list specific details here. That is Anthropic's intellectual property.
The real damage was that competitors, researchers, and the general public could read Anthropic's internal playbook. Not from a hack. Not from an insider. From a file that should not have been in the download.
Not model weights. Not customer data. Not API keys. What leaked was arguably worse for Anthropic's competitive position: the complete tool-use orchestration architecture. Feature flags. Model codenames. Unreleased capability references. The full agent routing logic that makes Claude Code work.
We are not listing specifics. That is Anthropic's IP.
Anyone who downloaded the package could read the entire agent architecture. Not from a breach. Not from an insider. From a config file that nobody validated before publish.
Why the second time matters
One leak is a mistake. Two leaks is a missing CI gate.
February 2025: first leak. Someone patches the .npmignore. Someone removes the source map. The specific version is fixed. No pre-publish scan is added. No regression test. No artifact inspection step in CI.
Thirteen months later, same root cause. Same file type. Different version. The recurrence was deterministic.
Incident response fixes the incident. It does not fix the category. If your post-mortem produces a config patch but not a pre-publish scan, the next leak is already scheduled.
Anthropic employs excellent engineers. That is the point. If a team this good can ship the same packaging mistake twice, the problem is not competence. The problem is that nothing in the toolchain inspects the output artifact before npm publish runs.
One leak is a mistake. Two leaks means the safety net is missing.
Fixing one mistake does not prevent the next one. If the first leak was fixed by hand but no automated check was added, the second leak was already inevitable.
This is not a criticism of Anthropic's team. They have excellent engineers. That is the point. If a team this talented can make the same mistake twice, the problem is not skill. The problem is that no tool checked for this kind of error before the release went out.
One leak is a mistake. Two leaks is a missing eval.
Incident response is not a systemic fix. If the post-mortem produced a config patch but not a pre-publish artifact scan in CI, the second leak was already deterministic.
Anthropic employs excellent engineers. That is the point. If a team building AI tooling cannot prevent the same packaging-stage failure from recurring, the gap is structural. No amount of engineering talent compensates for a missing CI gate.
The category: packaging-stage failures
You probably run a secrets scanner. Maybe SAST. Maybe npm audit. These tools scan what is in your repo.
Almost nothing scans what is about to leave your repo.
- Repo-stage failures: secrets in committed code, leaked
.envfiles. Tools exist. Most teams run them. - Packaging-stage failures: source maps in npm tarballs, test fixtures in Docker images, dev configs in production builds. Almost nobody checks.
The Anthropic leak was a packaging-stage failure. Their .gitignore was probably fine. But .gitignore and .npmignore are separate files with separate rules. When they drift, things ship that should not.
Same gap between .gitignore and .dockerignore. Your .gitignore excludes .env from version control. Your .dockerignore might not. Run docker build and your secrets are in the image layer. Different tools, different ignore files, same blind spot.
Most security tools check what is inside your project. Few tools check what is about to leave your project when you publish or ship it.
Think of it like packing a suitcase. You keep your passport safe at home, but if you accidentally pack it in a checked bag with no lock, it is exposed. The security was in the wrong place.
The Anthropic leak was the second kind. Their project was probably fine. But the tool that publishes the download had different rules than the tool that protects the project, and when those rules got out of sync, files slipped through. If you have asked Claude Code or Cursor to set up your project, it probably created one set of rules for you. It probably did not create matching rules for every way your project can be published.
Everyone scans what is in the repo. Almost nobody scans what is about to leave it.
Three separate config surfaces (.gitignore, .npmignore, .dockerignore) with zero enforcement coupling between them. Add MCP server configs that AI agents read at runtime, and you have four independent trust boundaries that drift silently.
What prevention looks like
The fix is a CI gate that inspects the output artifact before it crosses the trust boundary.
Before npm publish or docker build completes: scan the output. Source maps, .env files, oversized binaries, test fixtures. Not the repo. The package. What is actually about to leave.
DevSafe scans repos for secrets, cloud sync risks, and AI context leaks. Pre-publish artifact scanning is on the roadmap. This incident is exactly why.
The gap is clear. The question is what fills it.
Before you deploy or publish anything, something should check the output for source code files, passwords, oversized files, and test data that should not be public. Not your project folder. The actual thing you are about to ship.
DevSafe scans your projects for secrets, cloud sync risks, and AI context leaks. Pre-publish scanning (checking what you are about to ship) is on our roadmap. The Anthropic incident is exactly why.
The fix is not another config file. The fix is a CI gate that inspects the output artifact before it crosses the trust boundary.
Before npm publish, docker build, or any deployment pipeline emits an artifact: scan it. Source maps, .env files, oversized binaries, test fixtures, MCP server configs with hardcoded credentials. Not the repo. The artifact. What is actually leaving.
DevSafe scans repos for secrets, cloud sync risks, and AI context leaks today. Pre-publish artifact scanning is on the roadmap. This incident, and the broader pattern of MCP configs shipping with embedded credentials, is exactly why.
The 23-minute window
Twenty-three minutes from publish to detection. It did not matter.
By the time a human flagged it, automated systems had already replicated the package. npm caches. CI pipelines. Archive services. 41,000 GitHub forks. Every one of those copies is permanent.
npm unpublish removes the listing. It does not remove the bytes from every system that already pulled them. In 2026, the blast radius of a packaging mistake is permanent. Detection and response are necessary. They are not sufficient.
Anthropic responded well. They pulled the version, acknowledged the mistake publicly, minimized the fallout. But "minimized the fallout" is damage control, not prevention. The source code was already read.
Your team will eventually ship something that should not have been in the package. The question is whether your CI catches it before publish, or a researcher catches it after.
A security researcher found the leak 23 minutes after the update went live. But by then, the damage was already done.
41,000 copies cannot be taken back. You can pull the update, but you cannot delete it from every computer that already downloaded it.
Anthropic responded quickly. They removed the version. They acknowledged the mistake publicly. They handled it well. But "handled it well" means the damage was already done and they limited the fallout. It does not mean nobody read the source code.
The question is not whether a mistake like this will happen. The question is whether anything catches it before the release goes out.
Detection was fast. It did not matter.
npm unpublish removes the listing. Not the bytes. Damage control, not prevention.In 2026, the blast radius of a packaging-stage failure is permanent. npm unpublish is a UI operation, not a recall. Detection and response are necessary. They are not sufficient. The only strategy that works is prevention: scan the artifact before it leaves.
Your pipeline will produce a packaging-stage leak eventually. The question is whether your CI catches it before publish, or a researcher catches it after.
Frequently asked questions
Was customer data exposed?
No. The leak contained internal TypeScript source, feature flags, and model codenames. No customer data, API keys, or model weights.
Why does .gitignore not prevent this?
.gitignore controls what git tracks. .npmignore controls what npm publish includes. Separate files, separate rules. A file excluded from git can still ship in your npm tarball if .npmignore does not also exclude it. Same applies to .dockerignore.
What actually prevents this?
Add *.map to .npmignore. Then add a CI step that inspects the tarball before publish: npm pack --dry-run and scan the file list for source maps, .env files, and test data. Config files are necessary but not sufficient. Anthropic had a config fix after the first leak. It did not prevent the second.
Was customer data exposed?
No. The leak contained Anthropic's internal source code, feature names, and unreleased product references. No customer data, passwords, or AI model data was included.
Could this happen to projects built with AI coding tools?
Yes. AI coding tools like Claude Code and Cursor set up your project structure, but they typically create only one type of ignore file. If your project uses multiple publishing tools (app stores, package registries, container services), each one needs its own ignore file. Your AI assistant probably did not set all of them up.
How do you prevent this kind of leak?
Use a tool that checks what you are about to publish before it goes out. Manual review is not enough because the same mistake happened at Anthropic twice, 13 months apart, despite being fixed the first time.
Was customer data exposed?
No. The artifact contained internal TypeScript source, feature flags, model codenames, and the full tool-use orchestration architecture. No customer data, API keys, or model weights.
Does the same gap apply to MCP server configs?
Same failure category, different config surface. MCP server configs often contain hardcoded API keys and tool definitions. They ship with the project by default. If your packaging pipeline does not strip or redact them, they leak at the same trust boundary. Four independent ignore files (.gitignore, .npmignore, .dockerignore, MCP config) with zero enforcement coupling between them.
What does a systemic fix look like?
A CI gate that inspects the output artifact, not the repo, before the publish step executes. Scan for source maps, .env files, MCP configs with credentials, oversized binaries, and test fixtures. Manual review failed here twice in 13 months. The fix is automated, not procedural.