新しいnpm@3の依存関係ツリーに取り組む
Remy Sharp
2016年2月25日
0 分で読めます最近まで、SnykのCLIツールがサポートしていたのはnpm@2のみでした。snyk@1.9.0のリリースで状況は一変し、新しいnpm@3のディレクトリ構造を全面的にサポートしました。
この取り組みで直面した技術的な課題と、そこから生まれた新しいツールについてご紹介します。
npm@3の変更点
npm@2では、Nodeの依存パッケージは各Nodeパッケージのnode_modulesディレクトリにインストールされます。たとえば、requestモジュールのディレクトリは次のようになります。
上のスニペットからわかるように、すでにnode_modulesが何度も登場しています。これはそれほど悪いことではありませんが、重複が大量に発生する可能性があります。lodashのような人気のユーティリティが、1つのプロジェクト内に何度も何度も現れることもあります。
当初、npm@2では重複を排除するための処理が行われていましたが、npm@3では重複を完全になくすことを目指して、このディレクトリ構造を全面的にフラット化しました。npm@3での同じrequestパッケージは次のようになります。
ご覧のとおり、構造はまったく異なりますが、重要なのはNodeでモジュールを読み込む方法にはまったく影響がないことです。
これはSnykにどのような影響を与えるのでしょうか?
まず、CLIのパッケージをたどるロジックを全面的に書き直す必要がありました。従来のSnykはnode_modulesディレクトリをたどり、各サブディレクトリを順に調べてパッケージのツリーを構築していました。比較的シンプルな処理です。
ところが、npm@3のフラットなディレクトリ構造では、パッケージ間の関係をまったく把握できません。たとえば、上のnpm@3の一覧にあるasyncパッケージは、実際にはform-dataパッケージの依存パッケージであり、さらにform-dataはrequestの依存パッケージです。しかし、ファイルツリーからはこの関係がわかりません。
そこで、Snykのパッケージ解決機能を全面的に書き直し、snyk-resolve-depsというスタンドアロンモジュールとして切り出しました(Apache 2ライセンスのオープンソースです)。
このモジュールはsnyk CLIツールで使われていますが、単体のCLIツールとしてもインストールできます(npm install -g snyk-resolve-depsでインストールすると、snyk-resolveというユーティリティが使えるようになります)。
snyk-resolve-depsは、まずディレクトリ構造全体を調べ、物理ツリーを構築します。この物理ツリーを次の段階に渡して、パッケージをどこから読み込めるかを表す論理ツリーを作成します。
つまり、npm@2とnpm@3のどちらのディレクトリ構造もサポートでき、次のような仮想ツリーを作成できます。
これにより、Snykはnpm@2だけでなく、npm@3でインストールされたプロジェクトも問題なくサポートできるようになりました。パッチ適用に必要な正しいパスを特定し、脆弱性のあるすべてのパスを正確に報告できます。
「npm ls」との違いは?
npmのツールに詳しい方なら、こうしたツリーの確認に便利なnpm lsをご存じでしょう。
snyk-resolve-depsとnpm lsの大きな違いは、私たちのツールが論理ツリー全体を表示し、パッケージがプロジェクトに取り込まれた経路をすべて示すことです。
requestがnpmのコード(2.xブランチ)でどのように取り込まれているかを見ると、npm lsがディスク上で利用可能な内容について、次のように示していることがわかります。

一方、独自の解決方法では、異なる情報が得られます。これはnpm lsが間違っているということではありません。私たちが知りたいのは、requestを実際に何が読み込んでいるのかということであり、それをsnyk-resolve-depsで確認できます。

ご覧のとおり、requestモジュールは当初の想定よりも多くのパッケージに依存されています。このパッケージに脆弱性があった場合でも、脆弱性のあるパスをSnykが正確に把握できるようになりました。
snyk-resolve-deps
snyk-resolve-depsパッケージは、Apache 2オープンソースライセンスのもと、現在利用できます。グローバルにインストールすると、snyk-resolveという名前で使えます。
このCLIユーティリティには、--diskビュー(npm lsとよく似た内容を表示)や、特定の依存関係を絞り込んで出現箇所を探すための--filter X、--count Xなど、さまざまなフィルターやフラグがあります。詳しくはsnyk-resolve --helpをご覧ください。
今すぐnpm install -g snykを実行して、任意のパッケージやgithubリポジトリを匿名でテストできます。無料アカウントを作成すれば、プロジェクトの脆弱性を今すぐ監視できます。
キャプチャー・ザ・フラッグを始めよう
オンデマンドのバーチャル入門ワークショップを視聴して、キャプチャー・ザ・フラッグの課題の解き方を学びましょう。

