Audit a live site's JavaScript

Scan a live URL for public source maps, readable code and leaked credentials, and get a score out of 100. The same scanner that powers the public security scanner, from your terminal.

npx afterpack@latest audit <url> fetches the JavaScript a site ships and reports what a reader can pull out of it. It is the same scanner that powers the public security scanner: public source maps, how readable your own code is, leaked credentials, and, unscored, vendor code, dynamic-code sinks and the detected stack.

Audit is read-only. It modifies nothing, needs no account, and touches only what the URL serves publicly.

A separate tool from the obfuscation engine

audit does not run the obfuscation engine. It fetches a site's shipped assets and analyzes what is already exposed. None of the build flags apply to it.

Run it

$ npx afterpack@latest audit https://yoursite.com

The scheme is optional: a bare hostname is normalized to https://. The scanner fetches the page, renders it so client-side-loaded bundles are included, then analyzes every JavaScript resource it found.

Live URLs only

There is no local-directory mode. npx afterpack@latest audit ./dist is not supported. The argument must be a URL. Audit a preview deployment instead.

What it checks

CheckWhat it finds
Public source mapsA .map file next to any of your largest scripts, found by header, comment or a direct request, and whether it embeds your original source. A map with source caps the score at 10, a map with mappings only at 50. A public .git directory counts the same as a map with source.
Readable codeFor each of your own scripts, how much a reader gets back as plain code: English strings, meaningful names and property access, measured on the tokens. Each file is graded plain, minified or obfuscated. Worth 75 points, weighted by bytes. The per-token version of this question is the Protection Map.
Leaked credentialsPrivate keys, cloud secrets, payment secrets, repository and chat tokens, database URLs and bearer tokens, shown masked with their context. Worth 25 points. Emails, IP addresses and publishable browser keys are listed and not scored.
Vendor codeThird-party SDKs served from the site, identified by host, path or license banner. Listed separately and excluded from the score.
Hygieneeval(), the Function constructor, document.write and raw HTML sinks, third-party domains and the detected stack. Listed, not scored.

Exposed source maps

A source map chains your shipped bundle back to your original, readable source. Never ship one to production: an attacker downloads it and reads your code as you wrote it.

Audit catches it. AfterPack itself writes no .map sibling in a production build by default (see sourceMap.enabled and sourceMap.emitUrl), but it cannot stop your bundler from having already emitted one.

Reading the results

The CLI prints each phase as it completes, surfaces critical and high findings inline as they arrive, then closes with a summary box: the score out of 100, script counts, findings by severity and the detected stack. It ends with a list of every critical finding and a link to the full report on the web.

Read it top-down:

  1. Source maps first. A public map hands a reader your source as you wrote it, whatever else the build does. Remove every .map from production.
  2. Credentials next. Rotate any leaked credential, then stop shipping it.
  3. Readable code last. If your own files grade plain or minified, they have no meaningful protection. Run a build through AfterPack (Quickstart takes about five minutes).

Output is human-readable text by default. --diagnostics.format=json puts one JSON document on stdout instead — the findings, the score and the report link — with every human-readable line moved to stderr; --diagnostics.level=none silences the progress phases on top of that. The shareable report is always the web link the run ends with.

Not graded

A scan gets no score when the page has none of the site's own code, or when the scanner could not read it. The report reads Not graded instead of a number, and says why:

  • No JavaScript of its own. The page loads no script from the site itself, so there is nothing to grade. Scan a page that loads the app, such as a product page.
  • Blocked. The site answered the scanner with a bot check or an error page instead of the page.
  • Scripts not read. The page loads its own scripts, but the scanner could not read most of them. Scan again.

A blocked scan, or one whose scripts were not read, is never reused for the 30-minute repeat window, so a new scan runs right away. When only a few scripts could not be read, the scan is graded on the ones it read and the report says how many it missed.

Exit codes

CodeWhen
0The scan completed. Including when it found critical issues.
1The scan failed: an unreachable URL, a server-side error, the daily rate limit, or a stream that ended without completing.
64Misuse: no URL given, more than one URL, or the URL is malformed.

These are audit's own codes. The build exit codes an obfuscation run uses are separate.

Audit is not a CI gate

Because a completed scan exits 0 regardless of what it found, npx afterpack@latest audit … && deploy does not fail on findings. There is no severity threshold flag: read the findings from --diagnostics.format=json yourself if you want to gate on them. Use audit as a pre-release review step you read manually. The obfuscation run is the part that fails a build.

Unauthenticated scans are limited to 3 per IP per 24 hours, and a single site can be scanned 10 times an hour. Hitting a limit prints how long to wait and exits 1. A repeat scan of the same URL within 30 minutes returns the existing report and does not count toward the limit.

The AfterPack badge

Put the badge in your site's footer or README. It reads Protected by AfterPack while the latest scan of your host finds AfterPack output on the site's own code, no public source maps or credentials, and grade A. Otherwise it shows the latest score, or not graded while no scan of your host has graded the site. A host that was never scanned shows Scan with AfterPack. The badge links to the latest report and updates within an hour of a new scan.

AfterPack badge

Footer:

<a href="https://www.afterpack.dev/security-scanner/site/yoursite.com?ref=badge" rel="noopener" title="AfterPack security scan">
  <img src="https://www.afterpack.dev/badge/yoursite.com.svg?style=compact&theme=dark" alt="AfterPack badge" width="200" height="32" loading="lazy">
</a>

README:

[![AfterPack badge](https://www.afterpack.dev/badge/yoursite.com.svg)](https://www.afterpack.dev/security-scanner/site/yoursite.com?ref=badge)

Styles: compact (200×32) and wide (236×48) for footers, flat (20 px) for READMEs. Themes: dark and light. Every result page on the security scanner has these snippets for its host.

Next

  • Builds & CI: baking obfuscation into your release pipeline, and pinning a seed for reproducible output.
  • Best practices: what to mark, what to leave alone, and the source-map rule.
  • Security scanner: the same checks in your browser, no install, with the full shareable report.
  • Protection Map: the per-token view of your own build, once you're obfuscating.
  • What AfterPack does not replace: a leaked secret needs rotation; obfuscating it after the fact does not help.