agentsclimarketplace

Find production sourcemap

Skill abedegno/reverse-engineering-companion/plugins/reverse-engineering-companion/skills/find-production-sourcemap

Companion skills for mobile/web reverse engineering — pairs with android-reverse-engineering-skill

Install
npx -y skills add abedegno/reverse-engineering-companion --skill find-production-sourcemap

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Check whether a production web app ships its JavaScript sourcemaps before doing the hard work of reverse-engineering minified bundles. Surprisingly often the `.js.map` sibling URL is right there. Use when reverse-engineering a web app, a webview-based mobile app, or any system where the client is shipped as compiled JS.

SKILL.md

9.3 KB, ~2.3k tokens by cl100k_base, as published. Nobody here has run it

Find Production Sourcemap

Before spending a week reverse-engineering minified JavaScript, check if the deployment ships sourcemaps. Often they're right there at <bundle-url>.js.map. When they are, you get back the original source — variable names, file boundaries, comments, sometimes the TypeScript types — and the task transforms from "deobfuscate" to "read code".

This skill is cheap to apply: 30 seconds to test the hypothesis. When it pays off, it can collapse weeks of work to hours.

When this skill applies

  • The target is a web app, webview-wrapped mobile app, or hybrid app (Cordova / Capacitor / React Native bundled via Metro).
  • You have the URL of a JavaScript bundle loaded by the app, typically from DevTools' Network panel or from mitm capture.
  • You want to read the original source, not the minified blob.

If the app is pure native (Swift / Kotlin / Java) there's no sourcemap to find — go back to decompilation.

Workflow

Step 1: Identify a bundle URL

Open the target in Chrome with DevTools. In the Network panel, filter to JS and pick the largest bundle (usually the entry chunk or vendor chunk):

https://cdn.example.com/assets/index-Xx1Yy2Zz.js

Or pull bundle URLs from a mitm capture:

mitmdump -nr session.flows -f "~u .js$ & ~q" | head

Step 2: Try the obvious — fetch <url>.map

BUNDLE_URL="https://cdn.example.com/assets/index-Xx1Yy2Zz.js"
curl -sSI "${BUNDLE_URL}.map" | head -3

If you see HTTP/2 200 and content-type: application/json (or text/plain), congratulations — the sourcemap is shipped. Fetch it:

curl -sS "${BUNDLE_URL}.map" -o /tmp/bundle.map
file /tmp/bundle.map
#   /tmp/bundle.map: ASCII text, with very long lines  (or JSON data)

If it's a 403 / 404 / signature mismatch, sourcemap isn't shipped at this URL. Try variants:

  • Inline sourceMappingURL comment. The bundle often has //# sourceMappingURL=index-Xx1Yy2Zz.js.map as its last line. Check:
    curl -sS "$BUNDLE_URL" | tail -1
    
    If that's a non-obvious filename, fetch that one.
  • Hidden sourcemap (hidden-source-map Webpack option). Bundle has no sourceMappingURL comment but the .map file IS deployed. Try the .map URL directly anyway — sometimes it 200s.
  • Different path. Sourcemaps sometimes live at /sourcemaps/<hash>.map or in a separate CDN bucket. Grep the bundle for any /.+\.map URLs.
  • Available only with a header / cookie. Sentry sometimes gates them behind a specific X-Sentry-Token. Less common.

Step 3: Reconstruct the source tree

A few tools, in increasing capability:

# Option A: unwebpack-sourcemap (Webpack-style bundles)
npx unwebpack-sourcemap --output ./recovered /tmp/bundle.map

# Option B: source-map-unpack
npx source-map-unpack /tmp/bundle.map ./recovered

# Option C: the source-map npm library directly, for custom unpacking
node -e "
const sm = require('source-map');
const fs = require('fs');
const path = require('path');
const map = JSON.parse(fs.readFileSync('/tmp/bundle.map'));
sm.SourceMapConsumer.with(map, null, consumer => {
    consumer.sources.forEach(src => {
        const content = consumer.sourceContentFor(src);
        if (!content) return;
        const out = path.join('./recovered', src.replace(/^webpack:\\/\\/.*?\\//, ''));
        fs.mkdirSync(path.dirname(out), { recursive: true });
        fs.writeFileSync(out, content);
    });
});
"

For the source-map library route to work, the sourcemap must include sourcesContent (most do; some hidden-source-map configs strip it). If sourcesContent is missing you can sometimes still pull the source from the original URLs listed under sources[], but those are often gone from prod.

Step 4: Browse the recovered source

find ./recovered -type f | head -20
find ./recovered -name '*.ts' -o -name '*.tsx' -o -name '*.vue' -o -name '*.svelte' | wc -l

What you'll typically find:

  • TypeScript source with type annotations intact. Comments may or may not survive depending on the terser config.
  • Original file structure (src/components/Login.tsx, src/services/api.ts, etc.).
  • Named symbols: function names, variable names, exported types. Single-letter a, b, c becomes customerId, paymentInfo, sessionToken.
  • Configuration files: API endpoints, feature flag keys, third-party SDK initialization strings, sometimes embedded constants that should never have shipped to the client.

What you typically won't find:

  • Server-side code (sourcemaps only cover what's bundled into the JS).
  • Comments stripped by a comments: false minifier config.
  • Type definitions that were tsconfig.json declaration: false (they're erased at compile time).

Step 5: Search for high-value patterns

Once unpacked, grep is your friend:

cd recovered

# PRNG or seed handling
grep -rn 'Math.random\|seed\|Date.now()' --include='*.ts' | head -20
grep -rn 'xorshift\|mulberry\|sfc32\|xxhash' --include='*.ts' | head

# Authentication
grep -rn 'authorize\|client_id\|audience\|PKCE\|code_challenge' --include='*.ts' | head

# API endpoints
grep -rn 'apiBaseUrl\|API_BASE\|process.env.REACT_APP\|VITE_' --include='*.ts' | head

# Server / WS protocol
grep -rn 'websocket\|colyseus\|socket.io\|new WebSocket' --include='*.ts' | head

# Feature flags / experiments
grep -rn 'LaunchDarkly\|launchdarkly\|optimizely\|Statsig\|growthbook' --include='*.ts' | head

# Hardcoded secrets that should not have shipped
grep -rn '[A-Za-z0-9_-]\{32,\}' --include='*.ts' \
    | grep -v 'sourceMappingURL\|webpack' | head

Why sourcemaps end up shipped

A sample of reasons people leave .js.map in prod:

  • Sentry / Datadog RUM / Rollbar all need sourcemaps to resolve stack traces in production errors. Many teams deploy the maps to CDN so the error tracker can fetch them. Most of those teams forget to gate the maps from public download.
  • Default Vite / Webpack / Next.js / Rollup config emits sourcemaps. Disabling for prod requires an explicit sourcemap: false.
  • CI pipeline copies dist/** to the CDN. Whatever's in dist/ ships.
  • CDN provider sometimes serves any file in a deployed directory regardless of intent.

The combination of these means production sourcemaps are common — surprisingly so.

When the sourcemap isn't there

You've got the minified blob and need to work with it. Strategies:

  • Use Chrome DevTools' built-in pretty-printer ({} icon) for readable structure even without symbol names.
  • js-beautify for offline pretty-printing.
  • For named-symbol recovery from minified-but-not-obfuscated code, prettier --parser=babel + manual rename via your editor's rename-symbol is slow but works for small targets.
  • For Webpack bundles specifically, webcrack (https://github.com/j4k0xb/webcrack) splits chunks into modules and can sometimes recover module names from webpackChunkName magic comments.

Pitfalls

  • Don't run the recovered source. The unpacked files were minified for browser execution; they may have side effects on load, reference CDN URLs that 404, or trigger network calls. Read them; don't execute them.
  • Beware embedded credentials. Sourcemaps occasionally include .env-style files inlined by the bundler. Treat them as you would any leaked secret — don't share publicly, don't commit to a public repo, report to the operator if material.
  • Comments may be the most valuable part. Many devs document PRNG choice, auth contract details, "TODO: rotate this key" notes in comments that survive minification with default terser. Read them.
  • TS type definitions and runtime types are different. The recovered .ts shows what the developer believed about types; the runtime may diverge if there are casts or any types.

Disclosure considerations

A shipped sourcemap is not in itself a vulnerability — it's an information disclosure that lowers the cost of further analysis. Whether it's worth reporting depends on what was in it:

  • API endpoints + structure: probably not worth reporting separately (those are visible from any HTTP capture anyway).
  • Embedded secrets, internal-only endpoints, debug interfaces: worth reporting.
  • Comments revealing intended-private security mechanisms: judgement call; usually worth a private note.

If you do report, lead with the concrete impact (specific endpoint, specific embedded value), not the abstract presence of sourcemaps.

Pairs with

  • mobile-auth-replay — once you have the auth client source, the PKCE / state / nonce / audience values are right there in plain TS.
  • bit-exact-sim-validation — if the source includes a PRNG or simulation logic, you can port it and validate.
  • time-window-seed-bruteforce — recovered PRNG source tells you the exact algorithm to port for seed recovery.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.