Deployment hygiene
You spent effort making your shipped JavaScript hard to read. Then your build wrote a .js.map file next to it, and your deploy step copied it to the web server. If that happened, your original code — original names, original structure, often the original file text — is one HTTP request away from anyone who opens DevTools. This is the most common way protected JavaScript gets un-protected, and almost nobody decides to do it. They just don’t decide not to.
What a source map actually contains
A source map is a JSON file whose entire job is to reverse your build. It maps every position in the shipped bundle back to a position in your original source, and it carries:
- Original file names — your project’s real structure, path by path.
- Original identifier names — the variables, functions, and members that minification or obfuscation renamed are mapped straight back.
- The original source text, in full, whenever
sourcesContent is populated — which the inlineSources option does by default in many toolchains. In that case the map alone reconstitutes your project without touching the bundle at all.
Protection and source maps are exact opposites. One removes the mapping from shipped code back to intent; the other restores it perfectly. Both are useful. Only one belongs on a public web server.
Check whether you’re doing it right now
Two commands against whatever you currently serve:
# 1. Is a map sitting in your deploy output?
find dist -name '*.map'
# 2. Does the shipped bundle point at one?
grep -r "sourceMappingURL" dist
If the first finds a .js.map and the second finds a //# sourceMappingURL= comment, open the map in a text editor and search for sourcesContent. If it has entries, that file is your source code. A protected bundle beside a populated map offers an attacker no reason to look at the bundle.
Why it keeps happening
Not through a bad decision — through a default. Bundlers emit maps to help you debug, drop a sourceMappingURL comment into the output, and your deploy step copies the whole output folder. Every link in that chain is individually reasonable. The result is that the single setting which undoes your protection is the one nobody remembers to change. A build that obfuscates and then publishes the map has done a great deal of work to arrive exactly where it started.
The fix is one line — but don’t just delete them
The naive fix is to stop generating maps. Don’t. You want maps — you just want them private. A production stack trace from a protected bundle is unreadable without one, and throwing them away trades a security problem for a support problem.
The right pattern is three steps:
- Generate the map as part of your build, as usual.
- Do not deploy it. Strip
.map files (and the trailing sourceMappingURL comment) from the artifact that goes to your web server. Keep the maps in your CI artifacts or an access-controlled store.
- Read production traces internally by symbolicating them against the private map, rather than shipping the map so the browser can do it for you.
# in your deploy step, after the bundle is built:
find dist-protected -name '*.map' -delete
# and strip the trailing comment the bundler left behind
# so the browser stops asking for a file that isn't there.
Where JavaScript Obfuscator fits
Obfuscation raises the cost of reading your shipped code; a published map sets that cost back to zero. So the two have to be managed together. JavaScript Obfuscator keeps the debugging benefit without the disclosure:
- Each protected build carries a private identifier map. Keep it beside your CI artifacts, not on the web server.
- Local symbolication demangles a production stack trace back to readable names on your own machine — the map never leaves it, and nothing is sent to JSO or anyone else.
- The CLI’s
--source-map-evidence review helps a release owner confirm leak cleanup, manifest verification, and bundler cleanup order before a handoff — without sharing raw .map files, source-map contents, or original source paths. See the CLI reference.
None of this requires trusting a claim: deployment hygiene is a checklist you can run yourself.
The one thing to do today
Before you tune a single protection option, run find dist -name '*.map' against what you are serving right now. If it returns anything, that is your highest-severity, lowest-effort fix in front-end security today — and it costs one line in your deploy script. Then take the cleaned bundle and see what the obfuscator does to it.