Skip to content
Security
Skill

/reversing-obfuscated-javascript

Reverse engineer minified, bundled, and obfuscated browser/Node JavaScript — unpacking webpack chunks, recovering source from sourcemaps, undoing obfuscator.io string-array and control-flow obfuscation with webcrack/synchrony/restringer, and locating a signing or crypto routine

BOOST
From plugin
secskills
17094 skills
Install
$ npx -y skills add trilwu/secskills --skill reversing-obfuscated-javascript --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/reversing-obfuscated-javascript

Context preview

The summary Claude sees to decide when to auto-load this skill.

Reverse engineer minified, bundled, and obfuscated browser/Node JavaScript — unpacking webpack chunks, recovering source from sourcemaps, undoing obfuscator.io string-array and control-flow obfuscation with webcrack/synchrony/restringer, and locating a signing or crypto routine

SKILL.md

reversing-obfuscated-javascript.SKILL.md
name: reversing-obfuscated-javascript
description: Reverse engineer minified, bundled, and obfuscated browser/Node JavaScript — unpacking webpack chunks, recovering source from sourcemaps, undoing obfuscator.io string-array and control-flow obfuscation with webcrack/synchrony/restringer, and locating a signing or crypto routine in a live bundle via Chrome DevTools. Use when a page ships a huge minified bundle, when code is full of _0x hex identifiers and a rotated string array, when a .js.map is reachable, or when you must find where a request signature or token is computed.
verified: 2026-08-07

Reversing Obfuscated JavaScript

Client-side JavaScript ships the whole program to the reader — there is no stripped binary here, only code deliberately made unreadable. That changes the job: you are almost never recovering *missing* information, you are undoing a transformation. Identify the transformation first, reverse it with the tool built for it, and fall back to hand-written AST passes only for the custom layer no off-the-shelf tool knows.

When to Use

  • A page or extension ships a large minified/bundled `.js` you need to read
  • Code is full of `_0x1234` identifiers, a big string array, and a rotation IIFE

at the top — the obfuscator.io signature

  • A `.js.map` sourcemap is reachable, or webpack left `//# sourceMappingURL`
  • You must locate where a request signature, HMAC, token, or crypto key is

computed inside a running bundle

  • Reproducing a client-side algorithm (an anti-bot signal, a licence check, a

paywall gate) from the shipped code

When NOT to Use

  • **React Native / Hermes mobile bundles** (`index.android.bundle`,

`main.jsbundle`, Hermes magic bytes) — use `reversing-react-native-apps`.

  • **A custom bytecode VM or virtualized-JS obfuscator** where control flow is

interpreted, not just flattened — that is devirtualization; use `unpacking-protected-binaries` for the VM-lifting approach.

  • **Malicious JS in a compromised site or npm package** where the goal is IOCs

and behaviour, not readability — use `hunting-web-backdoors` for planted web payloads and `auditing-supply-chain` for a malicious package.

  • **Testing the web app itself** (the endpoints the JS calls, XSS, auth) — use

`testing-web-applications`; come back here only to recover a client-side algorithm it needs.

  • **WASM modules** loaded by the page — that is `analyzing-binaries` territory.

Identify the Layer Before Touching a Tool

Running the wrong deobfuscator produces plausible garbage. Read the first few hundred bytes and classify:

| What you see | Transformation | Reverse it with | | --- | --- | --- | | Short names, no whitespace, readable strings | Minification only | An unminifier / prettier + rename | | `webpackChunk`, a module map `{123: function(e,t,n){…}}` | Webpack/Rollup bundling | Unbundle to per-module files | | `//# sourceMappingURL=…` or a reachable `.map` | Nothing — the source is *right there* | Sourcemap recovery | | `_0x` hex names + one big string array + a rotation IIFE | obfuscator.io string-array | webcrack / synchrony / restringer | | Nested ternaries, `while(true){switch(_0x..)}` dispatcher | Control-flow flattening | AST pass to relink the switch | | `debugger` in a `setInterval`, self-defending function | Anti-debug / self-defense | Strip the guard before other passes |

Most real bundles are **layered**: webpack on the outside, obfuscator.io on a few modules, a hand-rolled string cipher on the one function that matters. Peel outermost first.

Sourcemaps: Try This First, Always

A reachable sourcemap ends the job before it starts — it contains the original, pre-transform source. Check for it every time, because a large fraction of "obfuscated" production bundles ship or leak one:

  • The `//# sourceMappingURL=` comment at the bundle's end, and the sibling

`.js.map` even when the comment was stripped (try `<bundle>.map`).

  • Webpack dev artifacts and source in `webpack://` paths inside the map.
  • Recover files with a sourcemap consumer — `unwebpack-sourcemap` or a short

`source-map` script walks `sourcesContent` back to a directory tree.

Treat a leaked production sourcemap as a finding in its own right when you are assessing the app, not just a convenience.

Unbundling and Deobfuscation

**`webcrack` is the first tool for a bundle**, because it does three of the layers at once: unminify, unpack webpack/browserify into per-module files, and undo obfuscator.io string-array and control-flow obfuscation. Run it, then read the module tree it produces rather than the single blob.

For a bundle that is *only* obfuscator.io, a dedicated deobfuscator is often cleaner: **`synchrony`** or **`restringer`** both resolve the string array, reverse the rotation, inline the decoder calls, and flatten the trivial control flow. Compare their output — they fail on different edge cases.

When no tool fully handles the custom layer, **write an AST pass** with Babel: parse to an AST, `@babel/traverse` to find the pattern (a specific decoder call, a constant-folded expression, the flattening dispatcher), transform the nodes, and regenerate. This is the durable skill — obfuscators change, but string-array decoding, constant folding, and dead-branch elimination are the same AST operations every time. Prototype the matcher in AST Explorer against the real code before scripting it.

Two failure modes to expect:

  • **A deobfuscator that runs the code to "evaluate" the string decoder** can

execute a payload. For untrusted or malicious bundles, do the string resolution statically or in an isolated sandbox — never `eval` an unknown bundle on your host to read it.

  • **Self-defending / debug-protection** re-obfuscates or spins a `debugger`

loop when tampered with. Strip the guard function first (delete the node, or override `setInterval`) or every downstream pass fights it.

Finding a Routine in a Live Bundle

When static reading is slow — a signing function buried

Read more
Ships withsecskills

**Security skills for Claude Code that encode the judgment professionals bring, not another wrapper around a scanner.** Offense, defense, and the reverse-engineering and code-audit core both sides share. Every skill is fact-checked against primary sources.

Get the whole plugin

Other skills on secskills.