Source Maps in Production: When to Ship Them (and When You Really Shouldn't)

TL;DR

  • Source maps reverse your minified/bundled code back to the original source. In the wrong hands, that means your entire codebase is readable.
  • Apple, Anthropic (twice), and Persona all leaked source code through exposed source maps in the last year alone.
  • Lighthouse and similar tools recommend source maps for debugging — but that doesn’t mean they should be publicly accessible.
  • Ship them to private error-tracking services (Sentry, Datadog, etc.). Keep them off your public servers and out of your npm packages.

What Are Source Maps, Exactly?

When you bundle or minify JavaScript/TypeScript, the output becomes nearly unreadable for humans. Source maps are JSON files (.map) that map that garbled output back to your original source — file names, line numbers, even the full original code if sourcesContent is included.

Browsers use them in DevTools to show you the real code when debugging. Build tools generate them by default sometimes. That’s the problem: defaults ship source maps whether you need them or not.

The Incidents That Made This Real

Apple App Store — November 2025

Hours after Apple launched a redesigned web version of the App Store , someone opened DevTools, noticed source map files loading, and extracted Apple’s entire front-end codebase  — Svelte components, TypeScript source, state management, API integration logic, routing config. All of it.

The extracted code was posted to GitHub. Apple filed a DMCA takedown  that nuked the original repo plus 8,270 forks. But the code had already spread. Apple then disabled source maps and updated their build process.

No secrets or user data leaked. But Apple’s proprietary front-end code was now public knowledge.

Anthropic’s Claude Code — February 2025 and March 2026

This one happened twice.

On launch day in February 2025 , a developer noticed an 18-million-character inline source map sitting at the end of the bundled cli.js in the @anthropic-ai/claude-code npm package. Anthropic pulled it within two hours. Root cause: a missing *.map entry in .npmignore — Bun generates source maps by default.

Then in March 2026 , it happened again. Version 2.1.88 shipped with a separate cli.js.map file — 59.8 MB, full sourcesContent intact. Researchers reconstructed roughly 1,900 TypeScript files and 512,000+ lines of code. The reconstructed repo hit 84,000+ stars on GitHub within days.

The source revealed internal features like an autonomous background agent mode and hidden feature flags — stuff Anthropic clearly didn’t intend to make public. Their statement  called it “a release packaging issue caused by human error, not a security breach.”

Fair enough — but the code was out there.

Persona — February 2026

Persona , an identity verification company used by major platforms, had source maps exposed on a non-production government subdomain. Researchers extracted 53 MB across 2,456 files  — the entire government dashboard codebase.

The root cause? A Vite dev configuration leaked to a subdomain. Persona disabled it within an hour and published a post-incident review . No secrets or customer data were exposed, but Discord reportedly dropped Persona as a vendor following the incident.

Why This Keeps Happening

Three reasons:

  1. Build tools generate source maps by default. Webpack, Vite, esbuild, Bun — they all do it unless you explicitly turn it off.
  2. Deployment pipelines don’t distinguish between files. If it’s in the build output, it ships. Nobody checks for .map files specifically.
  3. npm packages include everything unless you exclude it. If your .npmignore or files field in package.json isn’t explicit, source maps end up in the published package.

When You Should Use Source Maps

Error monitoring in production. Services like Sentry , Datadog , and Bugsnag  can ingest source maps privately. You upload the maps to them during CI — they never touch your production server. When an error fires, the service unminifies the stack trace on its end. You get readable traces, users get nothing.

Local development. Obviously. Keep devtool: 'eval-source-map' or equivalent in dev. No one’s arguing against that.

Internal tools behind auth. If the app is only accessible to your team, the trade-off shifts. Exposing source maps to authenticated internal users is usually fine.

When You Shouldn’t

Any public-facing website or app. If users can open DevTools and pull your maps, assume someone will. It’s not a matter of if.

npm packages. Unless your package is open source and the maps actually help consumers debug, leave them out. Add *.map to your .npmignore or use the files field in package.json to whitelist only what you intend to publish.

Anywhere proprietary logic or internal architecture is a concern. Source maps with sourcesContent are literally your source code. Even without it, file paths and structure reveal a lot.

How to Keep Source Maps Private

For web apps

Generate source maps but don’t serve them publicly. Most bundlers support this:

// webpack.config.js module.exports = { devtool: 'hidden-source-map', // generates .map files but doesn't reference them in the bundle };
// vite.config.js export default { build: { sourcemap: 'hidden', // same idea }, };

Then upload the .map files to your error-tracking service in CI and delete them from the deploy artifact.

For npm packages

Explicitly exclude maps:

# .npmignore *.map

Or better, use files in package.json to whitelist only what should be published:

{ "files": ["dist/**/*.js", "dist/**/*.d.ts"] }

Run npm pack --dry-run before publishing to see exactly what will be included. Make this a CI step.

For Next.js specifically

// next.config.js module.exports = { productionBrowserSourceMaps: false, // this is the default, but be explicit };

If you need source maps for error tracking, set it to true and configure your monitoring tool to upload them during build, then strip them from the deployment.

But Lighthouse Says I Need Them?

Lighthouse flags missing source maps because they help it analyze your code — bundle sizes, unused JavaScript, etc. That’s a development-time concern.

You can run Lighthouse locally with source maps enabled and still deploy without them. The audit is telling you “these would help me give better advice,” not “your users need these.”

Don’t let an audit score push you into shipping your source code to the world.

The Checklist

Before your next deploy, check these:

  • Web builds: using hidden-source-map or equivalent? Maps uploaded to error tracking, not served publicly?
  • npm packages: .npmignore excludes *.map? Or files in package.json whitelists only intended files?
  • CI: npm pack --dry-run step to catch accidental inclusions?
  • CDN/hosting: no .map files in the public directory?
  • Non-production environments: source maps disabled or behind auth?

Source maps are a great tool. Just don’t hand them to the internet.