Your Source Maps Are Publishing Your Source Code
Source map exposure can republish your entire codebase — comments, logic, and secrets — to anyone. Learn how to find leaked source maps and disable them in production.
You shipped your app and the production code looks safe. Open the browser, view the JavaScript, and it's a wall of unreadable, minified text — variable names crushed to single letters, all on one line. It feels private. It is not.
If your app shipped its source maps to production, that minified wall is a decoration. A source map is a companion file that translates the crushed-up production code back into the original, readable code you wrote — comments, function names, folder structure, and any secret you left in there. When source maps are public, anyone can rebuild your real source code in a couple of clicks. This is source map exposure, and it quietly hands strangers a copy of work you assumed was hidden.
The good news: this is one of the easier problems to find and fix, and many scanners miss it entirely. This post explains what source maps are, why shipping them republishes your codebase, how to check your own app in two minutes, and how to turn them off in production across the three build tools AI tools reach for most.
⚡ TL;DR
- A source map is a file that maps your minified production JavaScript back to your original, readable source code. Great in development, dangerous in production.
- If you ship source maps to production, anyone can download them and read your full source — including comments, internal logic, and any hardcoded secret.
- Many commodity scanners only read the minified bundle and never look for source maps, so this gap slips past them.
- Check by looking for
.mapfiles and//# sourceMappingURLcomments in your shipped JavaScript. Then disable source maps in your production build.
What a source map actually is
When you build a frontend app for production, your build tool runs your code through a step called minification. It strips whitespace, shortens variable names, and squeezes everything into the smallest file it can, so your app loads faster. The result is technically the same program, but miserable for a human to read.
That creates a problem. When something breaks in production and your error tool reports a crash, the error points at the minified file — line 1, column 48,200 — which tells you nothing. A source map fixes that. It's a separate file (usually ending in .js.map) that records exactly how each piece of the minified code maps back to the original code you wrote. Your browser's dev tools and error-tracking services read it and show you the real file, the real line number, and the real variable names.
So a source map is a translation table from "machine-optimized" back to "human-written." In development, that's a gift. The trouble starts when that translation table ships to the public internet alongside your app.
Why shipping them to production republishes your code
Here's the part founders miss: a source map does more than help you read errors. It contains enough information to reconstruct your original source files in full. Comments included. Folder names included. The TODO you left to yourself included.
Minification is often mistaken for a security measure. It isn't — it shrinks code, it does not hide it. But when source maps are absent, an attacker at least has to squint at obfuscated output to understand your logic. When source maps are present and public, that work disappears. They open dev tools, click into the Sources tab, and read your app exactly as it looked in your editor — clean, commented, organized.
Three things leak the moment a production source map is public:
- Your internal logic. How your app checks permissions, what it does before charging a card, which API endpoints it calls, and the names of every function. This is a map of where your soft spots are.
- Your comments. Developers and AI tools both leave notes in code —
// temporary, fix before launch,// admin override,// the real endpoint is.... Those ship inside the source map. - Any hardcoded secret. This is the dangerous one. A secret key buried in your code might be hard to spot in the minified bundle, but in the readable source map it sits in plain sight, on a named line, easy to grep for. We walk through exactly how someone does that in how attackers extract secrets from JS bundles.
One distinction this whole pillar turns on: not every key found this way is an emergency. A Stripe publishable pk_live key, the Supabase anon key, and the Firebase web config are public by design — meant to be in your frontend, so seeing them in a source map is not a leak. The emergencies are the secret keys: Stripe sk_live, the Supabase service_role key, and OpenAI or Anthropic keys. A public source map is bad regardless, because it exposes your logic and comments — but if it also exposes a secret key, that's a fire. The full breakdown lives in the complete guide to exposed secrets in frontend code.
Why many scanners miss this
This is where source map exposure gets quietly dangerous. A lot of automated scanners do a shallow pass: they pull your minified bundle, run a text search for key patterns, and report what they find. That catches a secret sitting in the bundle. It does not catch a secret that only appears in the source map, because they never download the map. It also misses the broader leak — the minified bundle might look clean while the source map next to it republishes your entire codebase. A scanner that stops at the bundle reports a green checkmark and moves on. You feel covered. You aren't.
Finding source map exposure means doing the extra step: noticing the //# sourceMappingURL pointer at the bottom of a bundle, following it, fetching the .map file, and inspecting what it reveals. That's more work than a quick grep, which is why it gets skipped — and why it's worth checking for deliberately rather than assuming a generic scan covered it. This is part of the difference between scanning the static file and probing the deployed app, which we get into in DAST vs SAST for AI-generated apps.
How to check your own app
You can confirm this yourself in about two minutes. No tools beyond your browser.
- Open your live app and open developer tools (right-click → Inspect, or press F12). Go to the Sources tab.
- Look at your file tree on the left. If you see your original, readable files — real folder names, real component names, clean indented code rather than one long minified line — your source maps are being served. The browser is reading them and showing you the original source. That same view is available to anyone who opens dev tools on your site.
- Find the pointer in the bundle. Open your main JavaScript file in the Sources tab and scroll to the very bottom. If you see a line like
//# sourceMappingURL=index-a1b2c3.js.map, that comment tells the browser (and anyone reading) where to fetch the source map. - Try to load the map directly. Take that
.mapfilename and request it in your browser, for examplehttps://yourapp.com/assets/index-a1b2c3.js.map. If a big file of JSON loads instead of a 404 error, your source map is publicly downloadable. Inside it, thesourcesContentfield holds your original code. - Search the map for secret prefixes. If the map loads, search it (Ctrl/Cmd-F) for
sk_live_,sk-,sk-ant-, andservice_role. Any hit there is a real secret exposed in your readable source — treat it as a leak and rotate it.
If step 2 shows you a wall of minified code and step 4 returns a 404, your source maps are not public, and you're in good shape on this specific issue.
Not sure if your source maps are exposed?
Run a free, read-only scan of your live app — no install, results in under a minute. Is My Site Hackable? looks past the minified bundle to the source maps most scanners skip.
Scan my app free →How to disable source maps in production
The fix is a build configuration change, not a code rewrite. You want source maps on while you develop and off in your production build. Here's how, for the three tools you're most likely using.
Vite (the default for Lovable, Bolt, and many React templates). Source maps are off by default in production builds, but they're easy to switch on by accident or via a template. Check your vite.config.js and make sure the build option is not set to true:
// vite.config.js
export default defineConfig({
build: {
sourcemap: false, // do not ship maps to production
},
});
Next.js. Next does not serve browser source maps in production by default. The setting to watch is productionBrowserSourceMaps — make sure it's not turned on in next.config.js:
// next.config.js
module.exports = {
productionBrowserSourceMaps: false, // keep maps out of the public bundle
};
Create React App (CRA). CRA generates source maps in production by default, so this one needs an explicit opt-out. Set the GENERATE_SOURCEMAP environment variable to false for your build. Add it to a .env file or to your build command:
# .env (or inline before the build command)
GENERATE_SOURCEMAP=false
After you change the setting, rebuild and redeploy, then repeat the check above — a config change does nothing until the new build is live. And if you found a secret key inside an exposed map, disabling the map is not enough on its own: the key was already public, so rotate it. The order of operations is in a key just leaked — rotate, audit, monitor.
FAQ
Are source maps a security risk on their own?
A public source map is a risk even with no secrets in it, because it exposes your full original source — your logic, your endpoints, and your comments — which makes the rest of your app easier to attack. If it also contains a secret key like sk_live or a service_role token, it's an active leak. The safe default is to keep source maps off your public production build.
Doesn't minifying my code protect it?
No. Minification shrinks code and makes it harder to read, but it does not encrypt anything, and it does not stop someone from running a text search. More importantly, if a source map is published alongside the minified bundle, the browser reconstructs your clean, original code automatically — minification's mild obscurity is undone entirely.
Should I ever use source maps in production?
You can generate them and keep them private — many error-tracking services let you upload source maps so you get readable stack traces from production crashes without serving the maps to the public. The rule is simple: maps are useful, but they should never be publicly downloadable from your live site.
The bottom line
A source map turns your minified production bundle back into the readable code you wrote — every comment, every function name, every hardcoded secret. Useful in development, a quiet leak in production. Worse, it's the kind of gap a shallow scanner skips, because checking for it means following the sourceMappingURL pointer and reading the .map file, not only grepping the bundle. Take two minutes to look, switch source maps off in your production build, and rotate anything secret you find. An attacker can pull your whole codebase from an exposed map in minutes — which is exactly why it's worth finding first, and re-checking on every deploy, because your AI builder can flip that setting back without telling you.
Find your gaps before an attacker does.
Is My Site Hackable? scans your deployed app for the exact issues in this article — exposed keys, missing RLS, open buckets — and tells you what's real and what's a false alarm.
Run a free scan →