mcpField
W
wakaru

wakaru

github.com/pionxzh開発1.1k67 回インストール3 日前に更新
リポジトリ

wakaru について

Wakaru は、本番 JavaScript を調査する開発者向けのコマンドラインスキルです。圧縮・変換済みコードの逆コンパイルや、対応バンドルのモジュール分割を行い、ソースマップや Bun 実行ファイルの抽出にも対応します。

主な機能

  1. 01圧縮・変換済み JavaScript の逆コンパイル
  2. 02対応バンドルのモジュール分割
  3. 03Bun 実行ファイル内のファイル抽出
  4. 04ソースマップによる名前の復元
  5. 05Vue 3 SFC アーティファクトの再構成
  6. 06React Server Components ペイロードのデコード

活用シーン

  1. 01圧縮されたスタックトレースの参照先を調査
  2. 02サイトや依存関係が配布するファイルを監査
  3. 03Bun 実行ファイルを起動せずに埋め込み JavaScript を抽出
  4. 04復元した Vue コンポーネントや RSC ペイロードを確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/pionxzh/wakaru --skill wakaru

インストール後、Claude Code で/wakaruを入力して読み込まれたか確認します。

詳細

Wakaru — JavaScript デコンパイラーとバンドル展開ツール

Wakaru は、本番用 JavaScript から読みやすいソースコードを復元します。バンドルをモジュールに分割し、トランスパイラーのヘルパー(async/await、クラス、JSX、スプレッド構文、オプショナルチェーンなど)を元に戻し、圧縮を解除します。構造を決定論的に復元し、名前の変更には保守的なヒューリスティックのみを適用します。ソースマップがない限り、難読化されたローカル変数名の多くは短いままです。

使用する場面

  • ファイルが1行に詰め込まれている場合や、_interopRequireDefault、 __awaiter、e,t,r のようなパラメーター、void 0、!0/!1 が多数含まれている場合。
  • webpack バンドル、IIFE webpack ブートストラップを含むサポート対象の Vercel ncc CommonJS 出力、Turbopack(Next.js 15.3 以降)のチャンク、または esbuild/Bun/Metro/Browserify/Cocos Creator 2.x/Closure ModuleManager/ SystemJS/AMD/Rollup/Vite のバンドルがあり、個々のモジュールが必要な場合。
  • Bun の単一ファイル PE、Mach-O、または ELF 実行ファイルに埋め込まれた JavaScript が必要で、実行せずに取り出したい場合。
  • Google Tag Manager のコンテナー(gtm.js)があり、Custom HTML と Custom JavaScript のコードを個別のファイルとして取得したい場合:wakaru gtm.js --unpack -o out/ を実行すると、各 __gtm_macro_<n> の内容と各タグの発火タイミングを説明する macros/、tags/、index.md が出力されます。
  • Bun の単一ファイル実行ファイルに保存されたすべてのファイル(バイナリーアセット、WebAssembly、ネイティブアドオン、埋め込みデータベースなど)が必要な場合。
  • コンパイル済みの Vue 3 コンポーネントの JavaScript があり、調査用にベストエフォートの .vue ファイルが必要な場合。
  • スタックトレースが、読み取れないベンダー提供または圧縮済みのコードを指している場合。
  • サイトや依存関係が実際に配布している内容を監査する場合。

セットアップ

CLI が必要です。npx を使って実行することをおすすめします(グローバルインストールは不要です)。

npx wakaru --version

繰り返し実行する場合は、1回インストールしてください:npm install -g wakaru@latest。 このドキュメントでは、グローバルにインストールされていない限り、wakaru は npx wakaru を指します。

基本的なワークフロー

1. 単一ファイルをデコンパイルする

圧縮またはトランスパイルされたファイルが1つの場合に使います。構造化された標準出力を得るには --json を指定します。-o を指定しない場合、デコンパイルされたソースは JSON の code フィールドに含まれます。-o を指定した場合、ファイルは引き続き書き出され、code は省略されます。

echo '<code>' | wakaru --json
# → {"code":"...readable...","warnings":[],"elapsed_ms":N}

また、ファイルからファイルへの変換もできます:wakaru input.js -o output.js(-o を省略すると標準出力に出力されます)。

2. バンドルを展開する(重要)

バンドルは何千ものモジュールに展開される場合があります。すべてをコンテキストに読み込まないでください。ディレクトリに展開し、JSON 出力を確認してから、必要なファイルだけを開きます。

wakaru bundle.js --unpack --json -o out/
# → {"detected_formats":["webpack4"],"modules":[{"filename":"module-0.js"},...],
#    "total":42,"failed":0,"warnings":[],"elapsed_ms":N}

出力先には新しいディレクトリを使用してください。Wakaru は、--force を指定しない限り、空でないディレクトリへの書き込みを拒否します。--force は、内容を上書きしても問題ないことを確認した場合にのみ使用してください。

その後、必要に応じて out/ 内の特定のファイル(例:out/module-0.js)を読み込みます。まずサイズで優先順位を付けて確認してください(ls -lS out/)。最大のモジュールは通常、ベンダー提供のライブラリです。アプリのコードは、より小さく、数が多いことがよくあります。

バリエーション:

wakaru dist/ --unpack --json -o out/          # scan a build-output directory
wakaru entry.js chunk.js --unpack -o out/     # explicit entry + chunk files
wakaru ./compiled-app --unpack --raw -o out/  # extract a Bun single-file executable safely
wakaru bun extract ./compiled-app -o raw/     # dump every embedded Bun file as the bundler emitted it

Bun の単一ファイル実行可能ファイルを抽出するには、実行可能ファイルのパスを明示する必要があります(ディレクトリのスキャンと標準入力で処理できるのは JavaScript のみです)。--unpack は JavaScript に類似したレコードを選択し、バンドル分割に渡します。標準エラー出力に note: <input> embeds N original source file(s) in Bun source maps と表示された場合は、そこに示されている wakaru bun extract コマンドを実行し、逆コンパイルされた出力より先に sources/ を確認してください。配布時の表現と比較する場合は、--raw を優先してください。 それでも文と宣言は分割され、チャンクが ESM としてリンクされるため、バイト列を厳密に確認する必要がある場合は wakaru bun extract を使用してください。

コンテナ自体が必要なタスクでは、代わりに wakaru bun extract を使用してください。検証済みの各ファイルレコードを raw/files/ 以下に書き込み、ローダーのメタデータとバイト範囲を raw/manifest.json に記録します。ファイルはバイト列として保存されます。ただし、"encoding": "utf16le"(Bun 1.4.1 以降の非 ASCII テキスト)のレコードは UTF-8 として書き込まれます。その場合、bytes と executable_range は保存された UTF-16 を示し、output_bytes は書き込まれたファイルを示します。

アプリが --sourcemap を付けてコンパイルされている場合、raw/sources/ にはバンドル前の元ファイル(型やコメントを含む TypeScript など)が格納され、マニフェストの sources リストは各元ファイルの path を output_path に対応付けます。逆コンパイルの前に確認してください。これらがある場合は、バンドルされた JavaScript ではなく、そのファイルを読み込みます。.. のパス要素は %2E%2E として書き込まれます。skipped_sources に記載されたレコードは、Wakaru が読み込めなかったマップを持つため、元ファイルがありません。その場合は、逆コンパイルされた JavaScript を使用してください。同じマニフェストを標準出力に出すには --json を追加します。 --include-internals を指定すると、不透明な Bun ソースマップ、JavaScriptCore バイトコード、module-info 領域も出力されます。source-map.bunmap を v3 JSON マップとして扱わないでください。 元ファイルはこのフラグを指定しなくても書き込まれます。 この抽出ツールは Bun 1.3.3 以降に対応しています。

バンドルに使用可能な名前のヒント(リソースパス、依存関係マップのリクエスト、元の入力パス)が含まれている場合、モジュールのファイル名は module-<id>.js ではなく、読みやすい相対パスになります。名前が重複する場合は一意になるよう調整されます。未加工の出力では、仮の抽出名が保持されます。

復元したモジュールを入力と照合する必要がある場合は、展開コマンドに --provenance を追加します。出力されたファイル名を out/provenance.json で検索し、元の入力と [start, end) のバイト範囲を確認してください。

3. マップがある場合に名前/元のソースを復元する
wakaru input.js --source-map input.js.map -o output.js   # recover names
wakaru extract input.js.map -o src/                       # dump sourcesContent

入力の --source-map は単一ファイル専用で、--unpack と併用できません。抽出されたモジュールには、バンドル内で生成された座標が保持されないためです。展開した出力のマップが必要な場合は、--emit-source-map を使用してください。

4. Vue 3 コンポーネントを SFC 成果物として復元する

入力がコンパイル済みの Vue 3 コンポーネント JavaScript、またはそれが含まれている可能性が高いバンドルの場合は、--vue-sfc を使用してください。復元はベストエフォートで行われ、追加の成果物として出力されます。展開モードでは引き続きすべてのモジュールの JavaScript が書き出され、復元可能な Vue モジュールについては、同じディレクトリに .vue 成果物も出力されます。

wakaru input.js --vue-sfc -o output.js
wakaru input.js --vue-sfc -o App.vue
wakaru bundle.js --unpack --vue-sfc --json -o out/

単一ファイルの場合は、-o を使って復元した Vue の出力先を指定してください。指定しない場合、標準出力には引き続き JavaScript が出力されます。バッチ分析では、--unpack --vue-sfc --json を使用して、まず JSON 出力を確認してください。各 modules エントリは出力成果物を記述します。kind は javascript または vue_sfc です。Vue 関連の status 値は、recovered_vue_sfc、vue_sfc_source_js、vue_sfc_fallback_js です。復元された .vue ファイルを開いてテンプレートを確認してください。ただし、復元がフォールバックした場合や、ヒューリスティックに基づく復元に見える場合は、対になる JavaScript 成果物も保持してください。復元された SFC を元のソースとして提示しないでください。

5. キャプチャした React Server Components ペイロードをデコードする(実験的)

React Server Components ペイロード(React の Flight ワイヤ形式)はデータであり、JavaScript ではありません。逆コンパイルや展開を実行しないでください。Next.js はこれをページ HTML に self.__next_f.push(...) 呼び出しとして埋め込みます。

wakaru rsc page.html -o rsc.json       # saved Next.js page or script
wakaru rsc payload.rsc -o rsc.json     # raw payload rows

JSON には、rows(16 進数の id、tag、kind、生の payload、および React が解析した場合の json)、assets(ペイロードが読み込むスクリプトとスタイルシートのパス)、scripts(ページの <script src> ファイル。ペイロード自体には記載されないバンドラーランタイムも含まれます。両方のリストをダウンロードして --unpack に渡してください)、problems(デコードできなかった行と push 呼び出し。残りは引き続き出力されます)が含まれます。format は raw または next.__next_f です。ペイロードのない入力は失敗します。モデル行では React の $ 参照("$L3")は文字列として保持されます。これらが記述するツリーは再構築されません。出力はどのリリースでも変更される可能性があります。

難読化の強い入力

文字列配列エンコード、制御フローの平坦化、VM プロテクターなど、同様の難読化については、まず webcrack を使って難読化を解除してください。展開と非最小化は Wakaru に任せてください。

# 1. Strip the obfuscation; leave unpacking and unminifying to Wakaru.
npx webcrack --no-unpack --no-unminify obfuscated.js > deobfuscated.js

# 2. Recover readable modules.
npx wakaru deobfuscated.js --unpack -o out/

書き換えレベル — 目的に応じて選択

  • --level minimal — 意味上の変更をほぼゼロに抑えます。**意味上のリスクを最小限にするため、セキュリティレビュー、監査、差分比較ではこちらを優先してください。**ただし、形式的な等価性を保証するものとして扱わないでください。
  • --level standard — デフォルトです。可読性と正確性のバランスが取れています。
  • --level aggressive — 可読性を最大限に高めます。より強いヒューリスティックにより、エッジケースでの動作が変わる場合があります。コードの理解だけが目的の場合に使用してください。
  • --unpack=inspect — 静的検査のため、より細かいスコープホイストの境界を再帰的に保持します。生成されるモジュールグラフでは、実行時の初期化順序が保持されない場合があります。このモードを使用すると、CLI は常に警告を出力します。可読性処理をスキップするには、別途 --raw を追加してください。--raw を指定すると --level は効果がありません。

デフォルトでは、Wakaru は自身の変換によって導入されたデッドコードのみを削除し、入力に元から存在していたデッドコードは保持します。到達可能性をすべて調べる場合は、--dce を使用してください。

出力の解釈

  • 終了コード 0 は成功、ゼロ以外は致命的なエラー(引数や I/O の不備)、または少なくとも 1 件のエラークラスの警告を示します。エラーは stderr に出力され、--json の出力は stdout に出力されます。
  • すべての JSON 警告の is_error フィールドを確認してください。is_error: false の項目は致命的ではありません。エラークラスの警告があるとコマンドはゼロ以外で終了しますが、Wakaru は JSON 出力とすべての成果物を書き込みます。エラークラスの警告がないモジュールは引き続き使用できます。
  • --diagnostics を指定すると、逆コンパイルまたは展開時に出力される宣言の競合(var と let/const の競合など)や、再解析に失敗する出力を検出できます。duplicate_declaration と output_parse_* の警告はエラークラスです。適法な var の重複宣言は許可されます。--diagnostics を指定しない場合、出力されたモジュールは再解析されません。
  • cross_module_class_call 警告(エラーではありません)は、そのモジュールが実行時に復元されたクラスを new なしで呼び出す可能性があることを示します。出力を実行する必要がある場合は、--level minimal を指定して再実行してください。
  • commonjs_export_unrecovered 警告(エラーではありません)は、ESM 出力モジュールが引き続き、一覧にあるエクスポートに exports または module.exports 経由でアクセスしていることを示します。これらのアクセスは実行時に ReferenceError をスローするため、そのモジュールのエクスポート範囲は不完全として扱ってください。
  • require() 呼び出し(遅延、条件付き、または副作用の後にあるもの)が残るモジュールは CommonJS のままです。ESM には require がありません。commonjs_require_unrecovered 警告(エラーではありません)は、ESM 出力モジュールが一覧にある指定子に対して引き続き require を呼び出していることを示します。これらの呼び出しは実行時にスローされます。
  • commonjs_require_of_esm 警告(エラーではありません)は、CommonJS 出力モジュールが ESM として復元されたモジュールを要求していることを示します。この場合、require はそのモジュールの名前空間を返します。置き換えられた module.exports の値、または相互運用処理が削除されたデフォルト値や、デフォルトエクスポートを持たない提供元のデフォルト値を読み取ると、代わりに名前空間が取得されます。また、その名前空間への書き込みは失敗します。
  • commonjs_exports_escape 警告(エラーではありません)は、あるモジュールが提供元の exports オブジェクトを別のモジュール内の関数、または Wakaru が追跡できない関数に渡しており、その提供元が ESM になったことを示します。その関数がオブジェクトに書き込む場合、実行時にスローされます。出力を実行する前に、その呼び出しを確認してください。
  • missing_imported_name 警告(エラーではありません)は、ESM 出力モジュールが、兄弟の ESM モジュールからエクスポートされていない名前をインポートしていることを示します。Node はこれをリンクできないため、その箇所と、そこを経由してインポートするすべてのモジュールを、ほかの場所で探すべき未検出のエクスポートではなく、壊れた出力として扱ってください。
  • --diagnostics を指定した場合、es_source_kept_commonjs 警告(エラーではありません)は、入力が ES モジュールからコンパイルされたように見えるものの CommonJS のままになったモジュールを示します。根拠と、CommonJS のまま保持された require 呼び出しも記載されます。そのモジュールのインポートは引き続き require 呼び出しです。インポートとして追跡してください。
  • .cjs または .cts の入力は CommonJS として逆コンパイルされます。require() 呼び出しと module.exports はそのまま残るため、出力には追跡対象のインポートがありません。--unpack にはまだ適用されません。.cjs 入力または復元されたモジュールでも、ESM 構文で出力されることがあり、Node はそれを .cjs ファイルから読み込めません。
  • バンドラーで展開出力を再ビルドする前に、__esModule を設定する CommonJS の兄弟モジュールをデフォルトインポートする ESM モジュールを確認してください。Node は module.exports を読み取りますが、バンドラーは exports.default(通常は undefined)を読み取ります。モジュール構文(import、export、import.meta、またはトップレベルの await)を含まないすべてのファイル(スクリプトを含む)を .cjs に変更し、指定子を更新して、出力ルートに {"type": "module"} を追加してください。
  • runtime_residual 警告(エラーではありません)は、そのモジュールが、出力では定義されていないバンドラーのランタイムヘルパーを引き続き呼び出していることを示します。たとえば、__turbopack_context__.L(...)(Turbopack のチャンク読み込み)、__turbopack_context__.P(...)(パス解決)、遅延 import() を囲む webpack の require.e/require.t、または出力内でリンクされていないモジュール ID を指定する webpack の require(id) などです(メッセージには、その ID が入力のいずれにもないのか、不透明なモジュール内にあるのか、ビルド内の複数のモジュールにあるのかが示されます)。通常どおりモジュールを読み取ってください。未解決なのはその呼び出しだけです。webpack の場合は、読み込まれるモジュールを含むチャンクファイルが入力に含まれていることを、一度確認してください。
  • 展開 JSON の failed は、エラークラスの警告(逆コンパイルの失敗、宣言の競合、出力の解析失敗など)が 1 件以上ある個別のモジュール数を示し、total はモジュール数を示します。failed > 0 の場合、必ずゼロ以外で終了します。failed < total の場合は、ほかのモジュールを通常どおり読み取り、失敗したモジュールを報告してください。
  • --vue-sfc を指定した場合、recovered_vue_sfc は .vue 成果物が書き込まれたことを示し、vue_sfc_source_js は復元されたモジュールに対応する JavaScript を示し、vue_sfc_fallback_js はモジュールが Vue のように見えたものの JavaScript のままになったことを示します。
  • 出力に難読化された短い名前(e、t、n)が含まれるのは、ソースマップがない場合には想定どおりです。Wakaru はコードから根拠が得られる場合にのみ名前を変更します。名前が重要な場合は、LLM によるリネームツールまたはソースマップを組み合わせてください。

安全性

分析する権限のあるコードのみを逆コンパイルしてください。第三者が提供するものを読むことは、正当なセキュリティ研究およびデバッグ活動です。同意を得ずに対象に対して使用すると、違法となる場合があります。法令遵守の責任はご自身にあります。

コメント