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-exposedfor 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 messageN potential source map(s) detected, listing up to ten resolved URLs, each labelledfrom <source>.source-maps-exposedonce 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 messageN 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 morewhen there are others. It lists up to 50 map URLs, each labelledfrom <script>with every script on the site that exposes it, counts the rest inadditional, and records insharedPageshow many crawled pages load the bundles.source-maps-inline: warns with the messageN inline source map(s) found, listing up to three sources with a count of the rest.source-maps: passes with the messageNo exposed source maps detectedwhen 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 ID | perf/source-maps |
| Category | Performance |
| Scope | Per-page |
| Severity | info |
| Weight | 3/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.
Related rules
- security/leaked-secrets: API keys and credentials exposed in the HTML or JavaScript a map would decode.
- content/dev-leakage: other development artefacts left in production.
- perf/unminified-js: the same build configuration seen from the other side.
- perf/js-file-size: the size an inline map adds to a bundle.
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.