Tools

Public asset inspection

Public asset inspection fetches the scripts and stylesheets a site serves and reads them for four things that should not be in a file handed to every visitor: credentials, internal hostnames and URLs, absolute server paths, and source maps exposing the original code. Every one of those files is already public — anyone can open them. The inspection is not gaining access to anything; it is reading what is being published and telling you what is in it.

What is looked for inside the files

Credentials: strings matching the key formats of common services, distinguished between the ones designed to be public and the ones that are not. A publishable identifier in a front-end bundle is correct; a server-side key in the same file is not.

Internal URLs: hostnames that resolve only inside a private network, staging addresses, administrative endpoints. None of these is a way in, and together they describe an infrastructure to someone who had no map of it.

Server paths: absolute filesystem paths left in a bundle, which name the build machine's directory layout and frequently the account the build ran as.

Sensitive comments: notes left in code that describe a workaround, a known weakness or an internal process.

Source maps: whether they are served publicly, and whether they embed the original source rather than merely mapping to it.

The distinction that matters most: which keys are meant to be public

Many services issue two kinds of key. One is designed to ship in a browser and is restricted by origin or by scope; the other authenticates a server and is restricted by nothing.

A front-end bundle containing the first is working as intended, and reporting it as a leak would be a false alarm that teaches people to ignore the check.

The second in the same file is a genuine finding, and it usually arrives by the same route: a developer needed a value at build time, used the one they had, and the build succeeded.

The two frequently look similar — same vendor, similar length, differing by a prefix. Telling them apart is most of the value of this check.

When a private key is found, renaming or removing it is not the fix. It has been publicly served for an unknown length of time, so it has to be rotated.

Source maps, and the two separate questions they raise

The first question is whether the map is served at all. A publicly fetchable map lets anyone reconstruct readable code from a minified bundle.

The second is whether the map embeds the original source text. A map that only records positions is far less revealing than one carrying the source itself, and both are ordinary build outputs.

Neither is a vulnerability. What they change is effort: reading minified code is tedious, reading original code with comments and names is not.

Plenty of teams publish maps deliberately, for error reporting that resolves stack traces in production. That is a legitimate trade and it is worth making on purpose rather than by default.

The middle path most teams want is uploading maps to the error-reporting service and not serving them from the site.

Why the coverage figure is part of the finding

A scan has a budget, and modern bundles are large. Not every served asset can be fetched and read within it.

So the check reports how much of the asset inventory was really inspected, alongside what it found.

A clean result over most of the inventory is meaningful. A clean result over a small fraction of it says very little, and presenting the two identically would be the most misleading thing this check could do.

This matters more here than almost anywhere else in a scan, because the consequence of a missed finding is a credential that stays public.

For the same reason a clean result is never the end of the work: secret scanning in the build pipeline catches what a sampled external inspection cannot.

What VeriFixScan uses

`exposure.secrets.private` reports credentials that are not meant to be public. `exposure.secrets.public_keys` reports the publishable identifiers separately, as information rather than as a defect.

`exposure.internal.urls` reports internal URLs and `exposure.internal.paths` reports server paths found in public assets. `exposure.comments.sensitive` reports revealing comments.

`exposure.sourcemap.public` reports publicly accessible source maps and `exposure.sourcemap.sources_content` reports whether they embed the original code.

`exposure.assets.coverage` states how much of the inventory was really inspected, which is what keeps every result above honest.

The limits, stated plainly

Only files the site already serves are fetched, within the scan budget. Nothing is guessed at, enumerated or brute-forced.

Detection is by pattern. An unusual credential format may not be recognised, so a clean result is evidence rather than proof.

Nothing found is stored or reproduced in the report beyond what identifies where it is.

Files loaded conditionally, or only from routes the crawl did not reach, are outside the inventory entirely.

Frequently asked questions

Is a key in my front-end bundle always a problem?
No. Many services issue a publishable key designed to ship in a browser, restricted by origin or scope. Those are reported as information. The finding is a server-side key in the same file.
I removed the key from the code. Is that enough?
No. It was served publicly for an unknown period, so it must be rotated. Removing it stops future exposure and does nothing about whoever already fetched the file.
Should I stop publishing source maps?
It depends on what you gain from them. Serving them publicly makes your code readable; uploading them to an error-reporting service instead keeps the stack-trace benefit without the publication.

Sources

Related

VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.

Scan a website