Fix guide · high · exposed_sourcemap
JavaScript source map deployed to production
vibecheck found a .map file referenced by your bundled JavaScript and reachable at the public URL. Source maps de-minify your bundle into the original TypeScript / TSX / JSX with comments, file structure, and developer notes intact.
Why it matters
The .js.map file maps minified production code back to original source. It's how your DevTools shows readable source when you hit a breakpoint. In production, the map is supposed to be either not deployed at all or accessible only through an authenticated tunnel (Sentry, Bugsnag).
When the map ships to the public URL alongside the bundle, an attacker:
- Downloads the bundle.
- Downloads the map.
- Runs
source-mapto reconstruct the original source tree. - Greps for secrets, internal API URLs, comments containing credentials, business-logic decisions, recently-removed-but-still-in-history code paths.
The specific risk depends on what your source contains. Common findings: .env constants compiled into the bundle, JWT secrets used for client-side validation, internal endpoint paths that aren't documented elsewhere, comments with developer notes, dead code paths that contain secrets nobody remembers existed. vibecheck re-runs its secrets detector against the reconstructed source — anything in there that we'd flag in normal client code now also gets flagged.
How to fix it
Stop emitting source maps to production. Per build tool:
Vite:
// vite.config.ts
export default defineConfig({
build: {
sourcemap: false, // never emit
// OR
sourcemap: 'hidden', // emit but don't link from bundle (Sentry-friendly)
},
});
Next.js:
// next.config.js
module.exports = {
productionBrowserSourceMaps: false, // default in newer versions, verify
};
webpack:
module.exports = {
mode: 'production',
devtool: false, // never emit
// OR
devtool: 'hidden-source-map', // emit but no //# sourceMappingURL= comment
};
esbuild:
{
"sourcemap": false
}
// or "external" — emits .map but no comment in the bundle
Rollup:
export default {
output: { sourcemap: false }, // or 'hidden'
};
SvelteKit / Remix / Astro: same primitives — check their build config; almost all delegate to Vite or esbuild under the hood.
After deploying with maps off, verify from outside:
# Find a script reference, then probe the .map URL.
curl -s https://your-app.com/ | grep -oE '/[^"]+\.js\b' | head -1
# /assets/main-abc123.js
curl -I https://your-app.com/assets/main-abc123.js.map
# Should return 404. If 200, the map is still live.
Also: search the bundle for the comment that points at the map. grep -o 'sourceMappingURL=[^\s]*' main.js shouldn't return anything if you're using 'hidden' mode.
If you need maps for error monitoring: upload them to Sentry / Bugsnag at deploy time. Both tools accept hidden source maps via their CLI and let you drop the comment from the bundle. Errors in production resolve to source frames the same way as if the maps were public — without exposing them.
If the maps have already shipped: assume an attacker reconstructed your source. Audit the reconstructed code (you can do this yourself: npx source-map-cli decode bundle.js.map > original.js) and treat anything sensitive in there as compromised. Rotate any secrets, audit for leaked internal URLs, review the build pipeline so it doesn't happen again.
Full guide: /blog/sourcemap-leaks-vibe-coded.
Did vibecheck flag this on your app?
If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.
Run another inspection