依存関係に注意せよ!マリシャス npm パッケージからの防御
JFrog、悪質なnpmパッケージの使用を検知・防止する3つのOSSツールを新たに発表
現代のソフトウェア プロジェクトは、そのほとんどがオープンソースのコードで構成されています。Log4Shell の脆弱性が発見された後、それらのコードを本当に管理しているのは誰か、ソフトウェアのサプライチェーンにおけるセキュリティ問題を検出して修正する責任は誰にあるのか、という疑問が大きな関心事となりました。
最近では、colors と faker という人気の npm パッケージが、メンテナによって意図的に破壊されました。この開発者である Marak Squires 氏は、これらのパッケージを使えなくする変更を加え、これらを使用しているアプリケーションを意図せぬ動作をさせるようにしました。実装された意図された欠陥は外観上のものであり(訳注:非ASCII文字を含めることで米国国旗を無限に表示させるという「欠陥」)、基本的には被害にあった多数のツールを緊急に修正する必要があったという程度の被害ですが、このシナリオはより深く、より問題があることを示しています。恐ろしいことに、これと同様に簡単に彼は「悪意ある危険なコード」を仕込むことができ得たわけで、今回の欠陥バージョンのパッケージをダウンロードしたことが判っている何十万ものマシン上でそれが実行され得たのです。
深く悩むべき事実は、多くの状況において、開発者にはほとんど見えない方法で、新しいコードがリポジトリからプルされ、プロジェクトで使用され、マシン上で実行される可能性があるということです。公開リポジトリから入手したコードを信頼するという前提は、多くのパッケージマネージャに深く根ざしていますが、この信頼はあまりに性善説に立ちすぎているかもしれません。今回の事件は、何年もかけて築き上げた信頼が、いつの日か破られる可能性があり、堅牢なパッケージの新バージョンでさえ信頼できないことを示しています。
npm パッケージのインストールに潜むリスク
最近の開発手法論でもたらす可能性のあるリスクを説明するために、npm パッケージをインストールするプロセスを検証し、アプリケーションが npm レジストリから悪意あるパッケージを誤ってプルし得ることを見てみましょう。
プロジェクトで特定のバージョンの npm 依存関係の使用を強制する一般的な方法は、package-lock.json ファイルを使用することで、許可されるライブラリのバージョンを指定します。可能な限り package-lock.json を使用し、依存関係のバージョンを正確に指定することを強くお勧めします。しかし、あまり知られていないことですが、現在の npm インストーラは、パッケージをグローバルにインストールする場合(npm
をオプション -g
または -global
と共に実行)、package-lock.json ファイルを尊重せず、package.json ファイルで指定された依存関係に応じて、パッケージの依存関係の最新バージョンを優先的にダウンロードします。これが、package-lock.json による保護を想定していたにもかかわらず、 アプリケーションが意図せぬバージョンの colors パッケージを使用してしまうことになった原因です。
任意の npm パッケージ(依存関係)の最新バージョンを検証せずにインストールすることは、悪意がある可能性(faker や colors の例のように、新バージョンで良からぬ変更がなされた場合等)からのみならず、依存関係を使用するコードを壊す可能性もあることから危険です(API が変更された場合等)。
npm パッケージ用の OSS ツールを JFrog が新たに公開
これらの事例を受けて、JFrog セキュリティ リサーチ チームは、欠陥のある可能性のある npm パッケージのインストールを検知・防止することを目的とした 3つの OSS ツールを公開しました。
- package_checker:パッケージの特定のバージョンが信頼できるかどうかを確認するツールです。サプライチェーン攻撃に使用されるパッケージの兆候を調査し、新しくリリースされたバージョンの潜在的なリスクを特定するために使用できます。チェック対象となる項目は以下の通りです。
- バージョン番号の著しいギャップ(例:faker npm パッケージのように、5.5.3 から 6.6.6 にジャンプするような場合)
- 長期間メンテナンスされていなかったパッケージのアップデート
- npm に表示されるバージョンと、リンク先の GitHub リポジトリとの不一致(特定のコードがリリースされたことが隠蔽されている可能性がある)
- バージョン公開からの経過日(公開直後のバージョンは十分な検証が済んでおらず、悪意のあるコードが含まれている可能性)
このツールは、開発者が依存関係のアップデートを決定する前に、使用パッケージの新バージョンを能動的にテストしたり、社内で使用しているパッケージの新バージョンをすべて組織的に監視したりするために使用できます。
- npm-secure-installer:
npm install
の安全なラッパーです。npm-shrinkwrap ロックファイルを含まないパッケージのグローバルインストールを拒否します。
Google の SLSA の重要な要件の1つは、依存関係の気密性です。つまり、依存関係は不変の参照にロックダウンされます。npmは、npm install
の初回実行時に自動的に作成される package-lock.json を使用することで、これを達成しています。しかし、npm を使用してグローバルツールをインストールする場合、npm はどのプロジェクトからも実行されないため、package-lock.json ファイルが存在していても使用されません。幸い npm はこのシナリオのために特別に設計された shrinkwrap アプローチを提供します。
npm-secure-installer
は、安全なアプローチを自動化します。パッケージに npm-shrinkwrap マニフェストがあることを確認してからインストールを実行します。
このツールは、開発者のワークフローを安全にするために、npm install
の代わりに使用することができます。 - package_issues_history: 問題のあるパッケージのアップデートを監視する試験的なツールで、特定のパッケージ バージョンに重大な変更が加えられていることが判明する前に、それらを発見することを目的としています。破壊的、あるいは悪意のある変更は様々な方法で生じる可能性があり、極端な(そして恐らく稀な)場合を除いて、良性の変更を誤検知しないような変更ルールを定義することは困難です。あるパッケージへの破壊的、あるいは悪意ある変更による唯一の確かな結果は、それに依存するパッケージの問題ということになるはずです。このツールに実装されている提案手法は、特定パッケージに依存しているプロジェクトで、バージョン更新後の数日間に作成された GitHub の “Issues” を追跡するというものです。人気のあるライブラリの場合、依存するプロジェクトの数が多いため、重大な変更に伴う “Issues” は、その変更と無関係のものと比べて極端に増加します。下のグラフは、colors パッケージとその依存ライブラリの “Issues” 作成率から、どのバージョンのアップデートが他よりも “Issues” が多いについての重要なことを明確に示しています。
常に最新に
これらのツールは、現代のソフトウェア サプライチェーンが直面するいくつかの問題を明らかにし、それを解決するための方法論を明らかにするための正しい方向への一歩であると考えています。JFrog は、最新のソフトウェア セキュリティの脅威に対処するための情報やオープンソース ツールを提供して開発者コミュニティをサポートすることに加え、開発者やセキュリティ チームに JFrog Xray による高度なソフトウェア サプライチェーン セキュリティ機能を提供します。悪意あるパッケージの高度な検出を含む Xray の製品アップデートについては、引き続きフォローしてください。