usability.cat
Issue Wiki

Exposed Source Maps

Publishing the blueprint of your house online — that's what leaving source maps in production does. Attackers can read your entire codebase.

What is this?

Imagine publishing the detailed architectural blueprints of your house online — every room layout, where the safe is, where the alarm wires run. Source maps do the same thing for your website. They are files that map your minified, compiled production code back to its original source code. They are invaluable during development for debugging, but in production they hand attackers a readable copy of your entire codebase, including comments, variable names, business logic, and sometimes even environment checks.

Why it matters

  • For your visitors: While source maps do not directly attack visitors, they give attackers a roadmap to find vulnerabilities in your code. An attacker who can read your original source code can find security holes orders of magnitude faster than one working with minified code. This puts all your visitors at greater risk.
  • For your business: Exposed source maps reveal your business logic, authentication flows, API endpoint patterns, validation rules, and sometimes hardcoded secrets that survived minification. Competitors can study your implementation. Attackers can find exactly where your code is weakest. It is like handing them the answers to the exam.
  • The standard: Source maps should never be accessible in production. Either do not generate them for production builds, or restrict access to them via server configuration. The .map files should not be served to browsers.
Source maps disabled in production
// next.config.js
const nextConfig = {
  productionBrowserSourceMaps: false, // default in Next.js
};
export default nextConfig;
Source maps exposed
// next.config.js
const nextConfig = {
  productionBrowserSourceMaps: true, // exposes your source code!
};
export default nextConfig;

// Or: .map files accessible at
// https://yoursite.com/_next/static/chunks/main-abc123.js.map

How to fix it

React / Next.js

Next.js does not expose browser source maps by default. But if you (or an AI tool) enabled them, turn them off.

// next.config.ts
const nextConfig = {
  // Do NOT set this to true in production
  productionBrowserSourceMaps: false,

  // If you need source maps for error tracking (Sentry, etc.),
  // upload them to your error service and don't serve them publicly
};

export default nextConfig;

If you use Sentry or another error tracking tool, upload source maps privately:

// next.config.ts with Sentry (source maps uploaded but not public)
import { withSentryConfig } from "@sentry/nextjs";

const nextConfig = {
  productionBrowserSourceMaps: false, // don't serve to browsers
};

export default withSentryConfig(nextConfig, {
  sourcemaps: {
    deleteSourcemapsAfterUpload: true, // delete after uploading to Sentry
  },
});

For Vite-based projects:

// vite.config.ts
export default defineConfig({
  build: {
    sourcemap: false, // no source maps in production
    // Or: 'hidden' — generates maps for error tracking but doesn't reference them
    // sourcemap: 'hidden',
  },
});

Plain HTML

If you use a build tool like Webpack, Rollup, or esbuild, configure it to skip source maps in production.

// webpack.config.js
module.exports = {
  mode: "production",
  devtool: false, // no source maps in production
  // devtool: 'source-map' would expose them — don't do this
};

If source map files already exist on your server, block access to them:

# nginx — block all .map files
location ~* \.map$ {
  return 404;
}
# Apache .htaccess — block .map files
<FilesMatch "\.map$">
  Require all denied
</FilesMatch>

You can also check if your site is currently exposing source maps by looking at the end of your JavaScript files for a comment like //# sourceMappingURL=file.js.map and then trying to access that URL.

Medium impactsecurity~1 paw

Source maps in production are handing attackers the keys to understand your code. The cat keeps its secrets close and expects you to do the same.

How the cat scores this

The scanner checks your JavaScript files for sourceMappingURL comments and then attempts to fetch the referenced .map files. If the map files are accessible (return a 200 status), the page is flagged. The scanner also checks for inline source maps (base64-encoded maps embedded directly in the JavaScript file), which are even worse because they cannot be blocked by server configuration. Each accessible source map file is reported individually.

Further reading

On this page