squirrelscan
GitHub

Exposed source maps: sourceMappingURL in production output

A sourceMappingURL comment or SourceMap header pointing at a map anyone can fetch. squirrel finds them in the page.

What a source map exposes

A source map lets a debugger show original source instead of the minified bundle. It always carries the original file paths and identifier names, and it usually embeds the source files themselves in sourcesContent. A map served publicly beside the bundle hands all of that to anyone who asks for it.

There are three positions to take. Ship no maps, which makes production errors hard to read. Generate them and restrict access, so only your team can fetch them. Or use hidden maps, which are uploaded to an error tracker and never referenced from the bundle at all. The third is usually the right answer.

What squirrel checks

The rule runs on every crawled page and emits these checks:

  • source-maps-exposed for the maps only this page is known to expose: an inline script or style, the page’s own header, or an external script no other crawled page loads. It warns with the message N potential source map(s) detected, listing up to ten resolved URLs, each labelled from <source>.
  • source-maps-exposed once per group of shared bundles. A map that comes from an external script more than one crawled page loads is grouped with every other map whose scripts are loaded by exactly the same pages. It warns with the message N source map(s) exposed by bundles shared across pages: <map>, <map>, <map>, naming up to three maps by path, or by full URL when they are not on the site’s own origin, and ending , and M more when there are others. It lists up to 50 map URLs, each labelled from <script> with every script on the site that exposes it, counts the rest in additional, and records in sharedPages how many crawled pages load the bundles.
  • source-maps-inline: warns with the message N inline source map(s) found, listing up to three sources with a count of the rest.
  • source-maps: passes with the message No exposed source maps detected when neither list has anything in it.

Four places are read. Inline <script> content is searched for //# sourceMappingURL= or the //@ form. Inline <style> content is searched for the /*# ... */ or /*@ ... */ form. The response headers SourceMap and X-SourceMap are read on the page itself. For an external script the crawl fetched, its own SourceMap header and its body are searched too, and a hit is labelled with the script URL. A reference to a data: URI inside a script or style body is counted as inline; anything else, including a header value, is resolved against the page URL and counted as exposed. Scripts and styles inside <noscript> are skipped, because a browser with scripting enabled never runs them. External URLs are deduplicated.

Every page in a shared group emits the identical check, so the report shows one finding per group with its pages listed, rather than one per page. A bundle every page loads is one finding; a bundle only one section loads is a second, with that section’s page count. The report’s warning total counts checks, so a page whose maps come from two groups adds two.

External stylesheets are not read, because the crawl does not fetch their bodies, so a map referenced only from a linked CSS file is missed. The rule does not fetch the map itself either, so a URL that returns 404 is still reported as potential.

How to fix it

Generate the map, upload it to the error tracker, and do not ship it:

export default {
  build: { sourcemap: "hidden" },
};

hidden writes the map file without adding the sourceMappingURL comment, so nothing on the public site points at it. It is still written into the build output, so exclude it from the deploy or delete it after the upload step. An error tracker keeps readable stack traces from the uploaded copy either way.

The common false positive is a development build audited by mistake. Source maps in a preview environment are normal and expected.

Rule IDperf/source-maps
CategoryPerformance
ScopePer-page
Severityinfo
Weight3/10

Enable / disable

Disable this rule

[rules]
disable = ["perf/source-maps"]

Disable all Performance rules

[rules]
disable = ["perf/*"]

Enable only this rule

[rules]
enable = ["perf/source-maps"]

enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.

Performance findings ship in every audit next to the SEO, security and agent experience rules. See Core Web Vitals for how an agent works through a report.

References

Check your site

Run squirrel audit https://example.com and open the Performance section of the report. Each detected map is listed with the file that referenced it. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

Type to search…

↑↓ navigate↵ openesc close