【ITニュース解説】The Largest NPM Supply Chain Attack Ever and How to Defend Against It
2025年09月26日に「Dev.to」が公開したITニュース「The Largest NPM Supply Chain Attack Ever and How to Defend Against It」について初心者にもわかりやすく解説しています。
ITニュース概要
npmの有名パッケージがフィッシングで乗っ取られ、暗号資産を盗む悪意あるコードが一時的に拡散された。これはオープンソースに依存する開発者への警鐘で、サプライチェーン攻撃から身を守る対策の必要性を示す。
ITニュース解説
2025年9月8日、JavaScriptのソフトウェア開発に不可欠なNPM(Node Package Manager)のエコシステムにおいて、極めて大規模なサプライチェーン攻撃が発生する寸前であった。この事件は、現代のソフトウェア開発における潜在的なリスクと、その対策の重要性を示す事例となった。
攻撃のきっかけは、わずか一つのアカウントの乗っ取りであった。攻撃者は、人気のあるNPMパッケージのメンテナー(保守管理者)に対し、NPMサポートを装った巧妙なフィッシングメールを送りつけた。このメールによって偽のウェブサイトへ誘導されたメンテナーは、自身のユーザー名とパスワード、さらには二段階認証(OTPコード)まで入力してしまい、アカウントの制御を攻撃者に渡してしまった。メンテナーが二段階認証を設定していたにもかかわらず、リアルタイムで認証情報を盗む高度な手口が使われたのである。
攻撃者は、この乗っ取ったアカウントを利用し、「chalk」や「debug」、「ansi-regex」といった非常に人気のあるNPMパッケージ計18種類に対し、悪意のある更新版を公開した。これらのパッケージは、毎週合計で20億回以上もダウンロードされるほど、多くのJavaScriptアプリケーションで広く利用されている。開発者が普段通りにnpm installコマンドを実行したり、新しいアプリケーションのビルドをデプロイしたりするだけで、約2時間もの間、知らないうちにこれらの改ざんされたバージョンを自身のプロジェクトに取り込んでしまう可能性があった。
公開された悪意のあるコードは、非常に危険な「仮想通貨ドレイナー」であった。これは主にウェブブラウザ環境で動作するように設計されており、typeof window !== 'undefined'のような条件でブラウザ環境かを検出し、window.fetchやXMLHttpRequest.sendといったネットワーク通信を司るAPIにフックを仕掛けることで、ユーザーのウェブブラウザ上で行われる仮想通貨取引を監視した。もしユーザーがMetaMaskのような仮想通貨ウォレットをアプリケーションで開いた状態で、不正パッケージを使用するアプリを操作していた場合、取引の際に送金先アドレスを密かに攻撃者のウォレットアドレスにすり替える機能を持っていた。Ethereum、Bitcoin、Solanaなど、複数の主要な仮想通貨ネットワークに対応しており、もし被害が拡大していれば、数百万ドル規模の金銭的損失が発生する可能性を秘めていた。
幸いなことに、セキュリティ研究者とNPMチームの迅速な対応により、この悪意のあるバージョンは公開からわずか2時間以内にNPMレジストリから削除され、GitHub上では影響を受けたプロジェクトに対する注意喚起が公開された。Vercelなどのプラットフォームも、ビルドが侵害された可能性のあるチームに通知を行い、被害は最小限に食い止められた。実際に攻撃者のウォレットに追跡された金銭的な被害は約600ドルと小額であったが、その潜在的な影響の大きさは計り知れない。もし主要なフィンテックアプリや仮想通貨取引所がこのペイロードを取り込んでいたら、想像を絶する事態になっていた可能性もある。
このような攻撃は「サプライチェーン攻撃」の典型的な例である。これは、自身が開発したコードではなく、そのコードが依存している外部のソフトウェアコンポーネントやサービスが弱点となり、攻撃の経路として利用されるケースを指す。現代のソフトウェア開発では、ほとんどのプロジェクトが多くのオープンソースライブラリに依存しているため、自身のコードだけでなく、依存するすべてのパッケージのセキュリティに注意を払う必要がある。
この大規模な攻撃から得られる教訓として、自身のコードベースとユーザーを守るために実践すべき7つの重要な対策がある。
第一に、依存関係のバージョンを固定することだ。^5.0.0やlatestのようにバージョン範囲を指定する「浮動バージョン」の使用は、新しいパッチやマイナーバージョンがリリースされた際に自動的に取り込まれるため便利だが、同時に悪意のある更新を意図せず導入してしまうリスクも伴う。これを避けるためには、package-lock.jsonやyarn.lockといったロックファイルをバージョン管理システムにコミットし、常に特定のバージョンのパッケージがインストールされるようにするべきである。CI/CD環境では、npm installではなく、ロックファイルに記述された通りの厳密なインストールを保証するnpm ciコマンドを使用する。また、RenovateやDependabotのようなツールを活用して、依存関係の更新を管理されたバッチで行うことも有効だ。ロックファイルを使用していれば、悪意のあるchalk@5.6.1が自動的にインストールされることはなかっただろう。
第二に、ライフサイクルスクリプト、特にpostinstallスクリプトの実行をブロックすることである。多くの悪意のあるパッケージは、インストール後に自動的に実行されるpostinstallのようなスクリプトを悪用して、システム上で任意のコマンドを実行しようとする。デフォルトでnpm install --ignore-scriptsを実行するか、CI環境ではnpm config set ignore-scripts trueを設定することで、これらのスクリプトの実行をブロックできる。信頼できるパッケージがこれらのスクリプトを本当に必要とする場合は、選択的に有効化することも可能だが、基本的には無効化するべきである。これはセキュリティ強化だけでなく、ビルド時間の短縮にも繋がる。
第三に、依存関係を継続的にスキャンすることである。Snyk、Trivy、Docker Scoutなどのソフトウェアコンポジション解析(SCA)ツールを使用し、プロジェクトが依存しているパッケージに既知の脆弱性や悪意のあるバージョンが含まれていないかを定期的に検出する必要がある。これらのスキャンを開発パイプラインに組み込み、重大なセキュリティ上の問題が発見された場合はビルドを自動的に失敗させるように設定することで、リスクを早期に発見し、対処できる。
第四に、npmの代わりにnpqのような代替ツールを使用することである。npqはnpmと互換性のあるコマンドラインツールだが、パッケージのインストール前に脆弱性情報(CVE)、NPMでの公開からの期間、パッケージの人気度、READMEファイルの有無といった様々なセキュリティ上の「赤信号」をチェックする機能が統合されている。これにより、問題のあるパッケージがシステムにインストールされる前に警告を受け取ることができる。
第五に、認証情報を強化することである。今回の攻撃では、メンテナーの二段階認証コードがフィッシングによって盗まれたため、特に重要なアカウント(NPM、GitHubなど)では、ハードウェアセキュリティキー(WebAuthn/U2F)の使用を強く推奨する。SMSや認証アプリによるOTPコードは、フィッシングサイトでリアルタイムに入力させることで盗まれる可能性があるが、ハードウェアキーはアクセスしているドメインが正規のものであるかを検証するため、フィッシング攻撃に対して非常に強い耐性を持つ。また、疑わしいメールのリンクは絶対にクリックせず、常に公式サイトに直接アクセスするという基本的な原則を守ることが重要である。
第六に、依存関係の更新時に不審な差分(diffs)に注意を払うことである。例えば、ごくシンプルなユーティリティライブラリの更新で、突然大量の難読化されたコードや、ネットワーク通信をフックするようなコード、あるいは仮想通貨ウォレットに関連するコードが追加されていた場合、それは明確な危険信号である。自動化された依存関係更新ボットを使用している場合でも、特に広く利用されているライブラリの更新では、その差分内容を注意深くレビューする習慣を身につけるべきである。
第七に、SBOM(Software Bill of Materials)を生成することである。SBOMは、アプリケーションがどのようなオープンソースコンポーネントやサードパーティ製ライブラリで構成されているかをリスト化した「ソフトウェア部品表」のようなものである。ビルド時にdocker buildx build --sbom=trueのようなコマンドを使用してSBOMを自動生成し、イメージレジストリにアップロードすることで、アプリケーションに含まれるすべてのソフトウェアコンポーネントを正確に把握できるようになる。これにより、将来的にあるパッケージが悪意のあるものとして報告された場合でも、過去のビルドのSBOMを検索することで、どのアプリケーションが影響を受けているかを迅速に特定し、対処することが可能になる。
今回のNPMサプライチェーン攻撃は、被害が最小限に食い止められたものの、その潜在的な危険性を浮き彫りにした。現代のソフトウェア開発において、すべての依存関係が潜在的な攻撃経路となることを認識し、自身のコードを守るだけでなく、利用するすべてのオープンソースコンポーネントに対しても警戒心を怠らず、ここで紹介した防御策を積極的に実践することが不可欠な姿勢となる。