npmの脆弱性とは、個々のパッケージに含まれるプログラム上の欠陥だけでなく、誰でもパッケージを公開でき、インストール時にコードが自動実行されるというnpmの仕組みそのものに由来する弱点を指します。npmはNode.jsの開発に欠かせない便利な仕組みである一方、その便利さと表裏の関係で攻撃者に狙われやすい性質を持っています。2025年9月にはnpmのパッケージが大規模に汚染される攻撃が相次いで発生し、その後も同種の攻撃は形を変えて続いています。この記事では、npmの脆弱性が何を指すのか、なぜ狙われるのか、実際に起きた攻撃事例、自分のプロジェクトが影響を受けていないかの確認方法、そして今すぐ実施できる対策までを、公式情報をもとに順を追って説明します。
npmの脆弱性を考えるときは、個別のパッケージが抱えるプログラム上のバグと、npmという仕組み自体が抱える構造的な弱さを分けて捉える必要があります。両者はどちらも「脆弱性」と呼ばれますが、対策の方向性が異なるためです。ここではまずnpmが何をする仕組みなのかを押さえたうえで、2種類の脆弱性の違いを説明します。
npm(Node Package Manager)は、JavaScriptのライブラリを探して導入し、管理するためのツールと、世界中の開発者が公開したライブラリが集まる保管場所(レジストリ)を合わせた仕組みです。「Node Package Manager」の略として紹介されることが多いのですが、npmの公式リポジトリでは、これは頭字語ではなく「npm is not an acronym」を再帰的に表した名称だと説明されています。(※1)
ここでいうパッケージとは、他の開発者が作った再利用可能なプログラムの部品を指します。開発者は npm install というコマンドを実行するだけで、必要なパッケージをレジストリから取得できます。
npmには依存関係という考え方があります。あるパッケージが別のパッケージを内部で使い、そのパッケージがさらに別のパッケージを使う、という連鎖です。自分が直接指定していないのに、間接的に取り込まれるパッケージを推移的依存(間接依存)と呼びます。また、パッケージには postinstall のように、インストールの前後で自動的に実行されるスクリプトを組み込めます。この自動実行の仕組みが、後述する攻撃の入口として繰り返し悪用されてきました。
ただし、この前提は2026年に変わりました。npm v12では、依存パッケージの preinstall・install・postinstall が既定では実行されなくなり、利用者が明示的に許可したパッケージのスクリプトだけが動く方式に変更されています。ただし既定が変わったのは依存パッケージのスクリプトであり、npm v11以前を使い続けている環境では従来どおり自動実行されます。(※2)
npmにまつわる「脆弱性」という言葉は、大きく2つの意味で使われます。ひとつは、特定のパッケージに含まれる既知の脆弱性です。これは正規のパッケージにたまたま含まれてしまったプログラム上の欠陥で、npm audit などのコマンドで検出でき、修正版へ更新することで対処します。npm audit は、プロジェクトの依存関係をGitHub Advisory Databaseに登録された脆弱性情報と照合する仕組みです。(※3)
もうひとつは、npmの信頼モデルに由来する構造的なリスクです。誰でもパッケージを公開でき、利用者がそれを信頼して取り込むという前提そのものが突かれるもので、サプライチェーン攻撃の入口になります。この記事で主に扱うのは後者です。既知脆弱性への対処も重要ですが、2025年に大きな話題となったのは、正規のパッケージが乗っ取られて悪意あるコードを送り込まれるという、信頼の仕組みを突く攻撃だったためです。
npmが攻撃者に狙われやすいのは、多くの開発者に使われる巨大さと、利便性を支える自動化の仕組みが、そのまま攻撃の効率を高める性質を持っているからです。1つのパッケージを侵害するだけで広範囲に影響を及ぼせるうえ、利用者が気づきにくい形で被害が広がります。ここでは、npmが持つ特徴を便利さと危うさの両面から説明します。次の表は、それぞれの特徴が持つ利点と、その裏側にあるリスクの対応を示したものです。
| npmの特徴 | 利用者にとっての利点 | 攻撃者に利用されるリスク |
|---|---|---|
| 世界最大級の規模 | 豊富なライブラリを再利用できる | 1つの侵害で多数のプロジェクトに波及する |
| 依存関係の自動解決 | 必要な部品が自動でそろう | 間接依存まで把握しきれず侵害に気づけない |
| インストール時のスクリプト実行 | セットアップを自動化できる | npm v11以前では、インストールしただけで悪意あるコードが動く |
| 誰でも公開できる開放性 | 誰もが開発に貢献できる | 公開までの審査が限定的で、悪意あるパッケージや乗っ取りが紛れ込む |
npmは世界最大級のパッケージレジストリで、登録されているパッケージは300万を超えます。1つのパッケージが多数のプロジェクトに使われているため、広く使われるパッケージを1つ侵害できれば、その影響は連鎖的に広がります。
規模の大きさは流通量にも表れており、Sonatypeの調査ではnpmを含む主要4レジストリの2025年のダウンロード数は9.8兆回、同年に新たに確認された悪意あるパッケージは45万4,648件とされています。(※4)
依存関係の深さもリスクを大きくします。1つのプロジェクトが直接依存するのは数個でも、推移的依存まで含めると数百のパッケージに膨らむことは珍しくありません。自分が明示的に選んでいない間接依存の中に侵害されたパッケージが紛れていても、利用者がそれに気づくのは容易ではありません。2025年9月の攻撃では、週あたり数億回ダウンロードされる基盤的なライブラリが標的となり、それらに依存する幅広いプロジェクトが影響範囲に入りました(※5)。
npmのパッケージには、インストール時に自動実行される postinstall や preinstall といったライフサイクルスクリプトを組み込めます。ネイティブモジュールのビルドなど正当な用途もある便利な仕組みですが、ここに悪意あるコードが含まれていると、npm install を実行しただけで任意のコードが動いてしまいます。
この挙動は2026年7月のnpm v12で変わり、依存パッケージの preinstall・install・postinstall は既定では実行されず、利用者が npm approve-scripts で明示的に許可したものだけが動くようになりました。ただし既定が変わるのはアップグレード後の環境に限られるため、npm v11以前を使い続けているプロジェクトやCI/CDでは、従来どおり自動実行されます。(※2)
特に問題なのは、被害がアプリケーションの稼働中ではなく、開発者の端末やCI/CD(コードのビルドや配信を自動化する仕組み)の環境でのインストール時点で起きることです。クラウドの認証情報やAPIキー、GitHubのトークンなどが、アプリがまだ動いていない段階で盗まれる可能性があります。2025年11月に確認されたShai-Huludの新しい亜種は、インストール前に動作する preinstall を起点とし、コードレビューやセキュリティスキャンよりも先に、しかもインストールが失敗しても実行される構造を持っていました(※6)。
npmレジストリには事前審査がなく、アカウントさえあれば誰でもパッケージを公開できます。2026年7月28日からは、公開されたパッケージが自動でマルウェアスキャンにかけられ、結果に応じて通常公開・手動レビュー保留・公開ブロックのいずれかに振り分けられるようになりましたが、人手による事前審査を経て公開されるわけではありません。
これは開発の裾野を広げる利点であると同時に、悪意あるパッケージが紛れ込む余地を生みます。そして2025年の大規模攻撃で共通していた起点は、正規パッケージのメンテナー(管理者)のアカウント乗っ取りでした。
攻撃者は、npmの公式サポートを装ったフィッシングメールで管理者から認証情報を盗み、そのアカウントで正規パッケージに悪意あるコードを混入した新しいバージョンを公開しました。利用者から見れば、いつも使っている信頼できるパッケージが、ある日を境に汚染された状態になります。攻撃の本質はプログラムの穴を突くことではなく、人の信頼を突くことにあったといえます(※7)。
なお、侵入の入口はアカウント乗っ取りだけではありません。GitHubは、攻撃の起点としてメンテナーのアカウント侵害に加え、プロジェクトのCI/CDワークフローを狙う経路を挙げており、2026年にはビルド環境の乗っ取りから不正なバージョンが公開された事例も報告されています。(※8)
npmの構造的な弱さは、2025年に実際の攻撃として繰り返し悪用されました。ここでは代表的な2つの事例を取り上げますが、注目したいのは被害の大きさそのものよりも、npmのどの弱点が突かれたのかという点です。次の表は、2025年9月以降の主な事案を時系列で示したものです。
| 時期 | 事案 | 突かれた弱点 | 主な手口 |
|---|---|---|---|
| 2025年9月8日 | chalk・debug等の汚染 | メンテナー乗っ取り | フィッシングで認証情報を窃取し暗号資産を狙うコードを混入 |
| 2025年9月15日 | Shai-Hulud | スクリプト自動実行と自己増殖 | postinstallで認証情報を盗み、他パッケージへ自動拡散 |
| 2025年11月 | Shai-Hulud 2.0 | preinstallによる早期実行 | インストール前に発火し検査を回避 |
| 2026年3月31日 | axiosの汚染 | メンテナー乗っ取り | 悪意ある版を公開、約3時間で削除 |
| 2026年5〜6月 | Mini Shai-Hulud | スクリプト自動実行と自己増殖 | 認証情報を盗み他パッケージへ自動拡散 |
2025年9月8日、chalkやdebugといった広く使われるパッケージが汚染されました。これらは週あたり数億回ダウンロードされる基盤的なライブラリで、あるパッケージ管理者がnpmサポートを装ったフィッシングメールにだまされ、認証情報を奪われたことが発端です。攻撃者はそのアカウントを使い、複数の人気パッケージに悪意あるコードを混ぜた版を公開しました(※9)。
混入されたコードは、ブラウザ上で動作して暗号資産の取引を密かに書き換え、送金先を攻撃者の口座にすり替えるものでした。管理者が汚染に気づいて修正版を公開するまでの短時間の出来事でしたが、その間に新規インストールを行ったプロジェクトは影響を受ける可能性がありました。1件のフィッシングが、広く信頼されたパッケージを通じてエコシステム全体へ波及しうることを示した事例です。
2025年9月15日には、Shai-Huludと名付けられたマルウェアによる攻撃が確認されました。これは従来の攻撃と異なり、自己増殖する性質を持つ点が特徴です。侵害されたパッケージがインストールされると、postinstall を通じてコードが実行され、npmやGitHub、クラウドサービスの認証情報を盗み出します。さらに、盗んだ権限を使って被害者が公開できる他のパッケージへ自動的に感染を広げ、人の操作を介さずに拡散を続けました(※1)。
影響を受けたパッケージ数は調査主体によって幅がありますが、第一波で180件を超え、その後の分析で数百件規模に達したと報告されています(※7)。攻撃はここで終わらず、2025年11月にはShai-Hulud 2.0と呼ばれる亜種が登場しました。この亜種はインストール前に実行される preinstall を起点とするよう変化し、静的解析による検査をすり抜けやすくなっていました。npmの脆弱性を突く攻撃が、一度きりではなく継続的に進化している実態がうかがえます(※6)。
攻撃は2025年で終わっていません。2026年3月31日には、広く使われているaxiosに悪意あるバージョンが公開され、短時間で削除される事案が発生しました。
さらに2026年5月から6月にかけては、Mini Shai-Huludと呼ばれる自己増殖型のワームによる攻撃が発生し、GitHubやOpenAI、Mercorといった企業が影響を受けました。
手口の骨格は2025年から変わっていません。メンテナーのアカウントを奪い、正規パッケージに悪意あるコードを混ぜ、インストール時の自動実行で認証情報を盗む。この型が繰り返されているという点が、対策を考えるうえで重要です。
これらの攻撃を知ると、自分のプロジェクトは影響を受けたのかが気になります。ただし、汚染されたパッケージが公開されている間にインストールした人すべてが必ず被害を受けるわけではありません。まずは影響を受けやすい条件を知り、そのうえで自分の環境を点検するという順序で確認すると、過度に不安を抱えずに対処できます。
2025年9月のchalk・debugの事案では、汚染された版が公開されていたのは短時間で、不正なバージョンは公開からおよそ2時間で削除されました(※9)。ただし、同じ攻撃者による別の事案では、汚染された版が7〜9時間にわたって公開されたままだったとの報告もあり、対象パッケージによって公開時間には幅があります。
そのため、影響を受けやすいのは、汚染が公開されていた時間帯に新しくインストールを行い、その時点のバージョンがロックファイルに記録され、かつ問題のパッケージを直接または間接に含んでいた場合に絞られます。これらの条件に当てはまらなければ、影響は限定的と考えられます。
一方で、Shai-Huludのように認証情報を盗む攻撃では、たとえ短時間でも該当期間にインストールした場合、盗まれた認証情報が後から悪用される可能性が残ります。心当たりがある場合は、影響の有無を確認するだけでなく、認証情報の再発行まで検討するのが安全です。米国のCISAも、2025年9月の注意喚起の中で、影響を受けた可能性がある組織に対して開発者の認証情報をただちに入れ替えるよう求めています。(※10)
自分の環境を点検するには、まず依存関係の中に問題とされたパッケージやバージョンが含まれていないかを調べます。npm ls パッケージ名 を実行すると、そのパッケージが依存ツリーのどこに、どのバージョンで含まれているかを確認できます。深い階層まで確実に確認するには npm ls パッケージ名 --all のように --all を付けます。また、そのパッケージがなぜ入っているのかをたどる場合は npm explain パッケージ名 が使えます。間接依存として取り込まれている場合もあるため、直接指定していないパッケージも対象に含めて確認します。
あわせて、既知の脆弱性を洗い出す npm audit を実行します。これは依存関係に既知の脆弱性がないかを調べるコマンドで、脆弱性の深刻度と影響を受けるパッケージを示してくれます。さらに、認証情報を盗む攻撃が疑われる場合は、身に覚えのない時期にインストールや更新が行われていないか、公開しているパッケージに覚えのないバージョンが存在しないかを確認し、少しでも懸念があれば認証情報を再発行します。加えて、ローカルやCI/CDに残ったnpmのキャッシュや、社内のアーティファクトリポジトリに汚染バージョンが残っていないかも確認します。
npmの脆弱性は仕組みに由来するため完全になくすことは難しいものの、利用者側の対策で被害に遭う確率を大きく下げられます。ここでは、効果と手間のバランスを踏まえ、優先して取り組みたい対策を順に説明します。次の表は、対策の優先度と、それぞれが主に効く場面を示したものです。
| 対策 | 優先度 | 主に効く場面 |
|---|---|---|
| ロックファイルの固定とnpm ci | 高 | 意図しない汚染版の取り込みを防ぐ |
| スクリプト実行を絞る | 高 | インストール時の自動実行を止める(npm v12では既定でオフ) |
| 公開直後のバージョンを避ける | 中 | 短時間で削除される汚染版を回避する |
| 既知脆弱性の継続監査 | 中 | 正規パッケージの既知の欠陥に対処する |
| アカウントと権限の保護 | 高 | 乗っ取りと被害拡大を防ぐ |
最初に取り組みたいのは、ロックファイルの固定です。ロックファイル(package-lock.json)は、どのパッケージをどのバージョンで使うかを記録しておくファイルで、これがあると誰がインストールしても同じバージョンがそろいます。一連の攻撃は、侵害された新しいバージョンが公開されることで広がったため、バージョンを固定することで、意図しない汚染版を取り込むリスクを下げられます。
ただし、通常の npm install は、状況によってはロックファイルを書き換えて新しいバージョンを取得することがあります。これを避けるには、CI/CD環境や新しく環境を構築する場面で npm ci を使います。npm ci はロックファイルの記録どおりに厳密にインストールし、記録との食い違いがあればエラーで停止します。この挙動により、固定したバージョンが勝手に更新されるのを防げます(※11)。
次に、インストール時に自動実行されるスクリプトを絞ります。前述のとおり、postinstall や preinstall はサプライチェーン攻撃で最も悪用されやすい入口のひとつです。新しいパッケージを試すときや、まだ十分に信頼できない依存関係を扱うときは、npm install --ignore-scripts を使ってスクリプトの実行を止められます。
常時無効化したい場合は、プロジェクトの設定ファイルである .npmrc に ignore-scripts=true を記載しておく方法があります。プロジェクト内の他の開発者にも同じ設定を共有しやすい利点があります。ただし、この設定は万能ではありません。一部のパッケージはインストール時のスクリプトでネイティブモジュールの取得やセットアップを行うため、無効化すると正しく動かなくなることがあります。すべてのプロジェクトで一律に無効化するのではなく、原則は止めておき、必要なパッケージだけ例外として扱う運用が現実的です(※11)。
なお、npm v12ではこの考え方が標準の動作になりました。依存パッケージのスクリプトは既定で実行されず、npm approve-scripts で信頼するパッケージだけを許可リストに登録する方式に変わっています。許可リストは package.json に書き出されるため、そのままリポジトリで共有できます。どのパッケージがブロックされるかは npm approve-scripts --allow-scripts-pending で事前に確認できます。npm v11以前を使っている環境では、引き続き上記の --ignore-scripts や .npmrc での設定が必要です。(※2)
一連の攻撃では、汚染された新しいバージョンが公開され、短時間で削除されるという経過をたどった事案が目立ちました。つまり、公開されたばかりのバージョンにすぐ飛びつかず、少し様子を見てから取り込むだけでも、汚染版をつかむリスクを減らせます。
npmには、公開から一定期間が経過していないバージョンをインストール対象から外す min-release-age という設定があります。npm CLI 11.10.0以降で利用でき、.npmrc に min-release-age=7 のように日数で指定すると、公開から7日未満のバージョンはインストールされなくなります。バージョンを明示せずに npm install した場合は、条件を満たす最新版が入ります。なお11.10.0より古いnpmでは、この設定は警告も出さずに無視されるため、CLIのバージョン確認が前提になります。(※12)
同種の仕組みはpnpmが2025年9月のv10.16、Bunが2025年10月のv1.3で先に導入しており、主要なパッケージマネージャーはいずれも対応しています。npmの初期実装には特定のパッケージだけ待機を免除する仕組みがありませんでしたが、その後 min-release-age-exclude が追加され、パッケージ名やパターンを指定して待機の対象から外せるようになっています。社内で管理しているパッケージを除外したい場合や緊急のセキュリティ修正をすぐ取り込みたい場合は、npm install --min-release-age=0 のようにコマンド単位で無効化する運用と組み合わせてください。
悪意あるパッケージを避けるだけでなく、正規のパッケージに後から見つかる既知の脆弱性にも継続して対処する必要があります。ここで使うのが npm audit です。依存関係に既知の脆弱性がないかを調べ、深刻度に応じて対応の判断材料を示してくれます。
注意したいのは、自動修正を行う npm audit fix を機械的に実行すればよいわけではない点です。npm audit fix は原則として package.json で許容しているバージョン範囲の中で修正版に更新しますが、範囲を超える更新が必要な場合は npm audit fix --force を求められます。--force は互換性のない更新(メジャーバージョンの変更)を伴うことがあり、動作が変わってプロジェクトが壊れることがあります。差分を確認し、テストを行ったうえで適用します。手元での実行に加えてCIでの定期実行を組み合わせ、依存関係の更新を継続的に監視する運用にすると、対応の漏れを減らせます。
攻撃の起点がアカウント乗っ取りである以上、認証まわりの防御は欠かせません。パッケージを公開する立場であれば、npmアカウントに多要素認証(2FA、パスワードに加えて別の要素で本人確認する仕組み)を設定します。GitHubは、フィッシングで盗まれやすいワンタイムパスワード方式から、セキュリティキーなどを使うFIDOベースの2要素認証への移行を進める方針を示しており、選べる場合はそちらが安全です。CI/CDで使うトークンは、読み取り専用や対象を限定した権限にとどめ、漏れたときの被害を小さくします。
利用する立場でも、GitHubやクラウドの認証情報が開発環境やCI環境に置かれている場合、それらがスクリプト経由で狙われることを踏まえ、権限を必要最小限に絞る考え方が有効です。侵害を前提に、盗まれても被害が広がりにくい状態を作っておくことが、被害の連鎖を止めることにつながります(※11)。
利用者側の対策と並行して、npmを運営するGitHubも仕組みそのものの見直しを進めています。2025年9月の一連の攻撃を受けて、GitHubは認証と公開の方法を段階的に変更すると発表しました。利用者の対策と基盤側の変化の両方を知っておくと、今後の運用の見通しを立てやすくなります。
発表された変更の柱は3つあります。1つ目は、ローカルからパッケージを公開する際の多要素認証の必須化です。2つ目は、公開に使うトークンの有効期間を制限し、長期間有効な従来型のトークンを段階的に廃止することです。3つ目は、トラステッドパブリッシングの推奨です。これは、長期間有効なトークンの代わりに、CI/CDのワークフローから短命の識別情報を使って安全に公開する仕組みで、盗んだ認証情報が悪用される余地を狭めます(※7)。
これらの変更は2025年10月から段階的に適用されました。まず10月13日に、新規に作成する書き込み権限付きの細分化トークンの有効期間が既定7日・最長90日に制限され、あわせてTOTPによる二要素認証の新規設定が無効化されました。新規設定ができなくなっただけで、すでに設定済みのTOTPは当面そのまま使えます。続いて12月9日には、有効期限を設けずに使えていた従来型(クラシック)トークンがすべて失効しました。同日以降、npm login で得られる認証は2時間で失効するセッショントークンに変わり、長期間有効なトークンは使えなくなっています(※13)。
ただし、トラステッドパブリッシングの対応環境は拡大の途上であり、当初はGitHub ActionsとGitLab CI/CDに限られていましたが、2026年4月にCircleCIが加わり、現在はこの3つに対応しています。対応環境は今後も広がる見込みです。(※14)また、Azure Pipelinesなどへの対応も拡大作業中で、セルフホストのランナーも対象外です。対応外のCI/CDを使っている場合は、90日ごとにトークンを更新する運用を続ける必要があります。なお変更は現在も続いており、二要素認証を回避するトークンについても、2026年8月のアカウント側の変更と2027年1月の直接公開の制限が予告されています。
こうした基盤側の強化が進んでも、リスクが完全になくなるわけではありません。攻撃者は手口を変えて対応してくるため、利用者側の対策と組み合わせて多層的に備える姿勢が引き続き求められます。
ここまで説明した npm audit などの自動的な仕組みは、既知の脆弱性を効率よく洗い出すうえで有効です。ただし、これらのツールが検出できるのは、あくまでデータベースに登録済みの既知の欠陥が中心です。レジストリ側でも公開時のマルウェアスキャンなどの自動検査は行われていますが、正規のパッケージに紛れ込んだ悪意ある挙動や、複数のパッケージやアプリ固有の実装が組み合わさって生じるリスクまでを、自動スキャンだけで拾いきることは難しいのが実情です。
近年はAIによる自動診断も登場していますが、npmの脆弱性のように、仕組みの信頼を突く攻撃が絡む領域では、機械的な検査だけで安全性を判断しきることは困難です。だからこそ、専門家が実際に手を動かして挙動を検証する手動の脆弱性診断やペネトレーションテスト(疑似的な攻撃を行って弱点を洗い出す検査)が重要になります。
ユービーセキュアは、Webアプリケーションを中心に、専門の診断員による手動の脆弱性診断を提供しています。ツールによる自動検査では見落とされやすいリスクを、人の目と手で確かめることに重きを置いています。npmをはじめとする依存関係を含めて、自社のアプリケーションが抱えるリスクを見極めたい場合は、手動診断という選択肢を検討する価値があります。
npmの脆弱性は、個々のパッケージのバグにとどまらず、誰でも公開でき、インストール時にコードが自動実行されるという仕組みそのものに根ざしています。だからこそ攻撃者に狙われやすく、2025年9月のchalk・debugの汚染やShai-Huludワームのように、正規パッケージを乗っ取る攻撃が現実に繰り返されてきました。これらは一度きりではなく、形を変えて続いています。
一方で、利用者側の対策で被害に遭う確率は大きく下げられます。まずはロックファイルを固定して npm ci を使い、インストール時のスクリプト実行を絞るところから始めるのが取り組みやすい第一歩です。そのうえで、既知脆弱性の継続的な監査やアカウントの保護を重ね、GitHub側の基盤強化とあわせて多層的に備えます。自動的な検査で拾いきれないリスクが気になる場合は、専門家による手動の脆弱性診断を検討し、自社のアプリケーションが抱える弱点を確かめることをおすすめします。
参考
※1 GitHub|npm/cli: the package manager for JavaScript
※2 GitHub Changelog|Upcoming breaking changes for npm v12
※3 GitHub Blog|Advisory Database now powers npm audit
※4 Sonatype|2026 State of the Software Supply Chain Report
※5 Trend Micro|NPMサプライチェーン攻撃の現状と分析
※6 Trend Micro|Shai-hulud 2.0キャンペーンがクラウドと開発者エコシステムを標的に
※7 GitHub|Our plan for a more secure npm supply chain
※8 The GitHub Blog|Disrupting supply chain attacks on npm and GitHub Actions
※9 Semgrep|Security Alert | chalk, debug and color on npm compromised in new supply chain attack
※10 CISA|Widespread Supply Chain Compromise Impacting npm Ecosystem
※11 OWASP|NPM Security Cheat Sheet
※12 npm Docs|config - min-release-age
※13 GitHub Changelog|npm classic tokens revoked, session-based auth and CLI token management now available
※14 GitHub Changelog|npm trusted publishing now supports CircleCI