攻撃者は開発者の認証情報を盗まずにnpmパッケージを乗っ取れる

npmの「Trusted Publishing」の仕組みに欠陥があり、攻撃者が開発者のnpmアカウントやGitHubアカウント、公開用トークンを侵害することなく、正規パッケージに悪意あるアップデートを公開できる恐れがあることが分かりました。

研究者は、合計ダウンロード数が1000万を超える1,500以上のパッケージが影響を受ける可能性があると特定しています。

この弱点が特に懸念されるのは、AIコーディングエージェントがnpmの依存パッケージを自律的に選定・インストール・実行するケースが増えているためです。

悪意あるパッケージのリリースは、もはや開発者を説得して手動でインストールコマンドを実行させる必要がありません。コーディングやビルド、CIのタスク中にエージェントに選ばれさえすれば足ります。

npm Trusted Publishingは、CI/CDパイプラインから長期間有効なレジストリトークンを排除する目的で設計されました。

この仕組みでは、GitHub Actionsのワークフローが有効期間の短いOpenID Connect(OIDC)トークンを取得し、それを時間制限付きのnpm公開用認証情報と交換します。

このモデルにより、ビルドログやリポジトリ、自動化システムからシークレットが漏えいするリスクを低減できます。

しかし、信頼関係は当初、GitHubリポジトリのスラッグ、つまり人間が読める形式のowner/repositoryパスに依存していました。スラッグは永続的なものではありません。

リポジトリの名称変更、移管、削除が行われたときや、所有者が名前を変更したり姿を消したりしたときに、そのスラッグが再び取得可能になることがあります。

GitHubのOIDCトークンには、repository_idやrepository_owner_idといった不変の識別子が含まれており、名称変更や移管後も維持されます。ところが、npmは当初、Trusted Publishingをこれらの識別子に紐付けていませんでした。

その代わり、最初に信頼された公開が成功するまでは、紐付けが再取得可能なスラッグに関連付けられたままになる可能性がありました。

これがパッケージ乗っ取りの経路となります。攻撃者は放棄されたGitHubのパスを取得し、想定されるファイル名のワークフローを作成してGitHub ActionsのOIDCトークンを入手し、それを有効なnpm公開用認証情報と交換できます。

元のメンテナーの認証情報やリポジトリへのアクセスは必要ありません。

Bloom Securityは、自社が所有するリポジトリとnpmスコープを使い、管理された環境でこの攻撃を実証しました。

Securityincident response

研究者によると、再取得したスラッグの下に新規作成したリポジトリから、旧リポジトリの場所を依然として信頼しているパッケージに対して公開できたということです。

攻撃に成功すると、被害パッケージの正規の名前で新バージョンを公開できます。そのダウンロード実績による信頼性や、依存関係グラフ上の既存の位置づけをそのまま引き継ぐことになります。

悪意あるリリースにはpostinstallライフサイクルスクリプトを仕込むことができ、開発者やCIシステム、自動化ツールがnpm installを実行した際にコードが動作します。

影響は直接の利用者にとどまりません。乗っ取られたパッケージが1つあれば、推移的依存関係を通じて下流のプロジェクトにも波及します。リポジトリのIDを検証できていないという不備が、広範なソフトウェアサプライチェーンの事案に発展しかねません。

Bloom Securityが「SlugFest」と名付けたこの問題は、npmが当初、不変のリポジトリIDではなく、変更可能なGitHubリポジトリ名を信頼していたことに起因します。

乗っ取られるnpmパッケージ

研究者は、プロベナンス(来歴情報)だけでは攻撃を防げない可能性があると警告しています。ツールが、パッケージが署名されているかどうかしか検証せず、そのプロベナンスがメンテナー管理下の想定リポジトリを指しているかを確認しない場合、Sigstoreのアテステーションが有効に見えてしまうことがあるためです。

今回の研究は、ソフトウェアサプライチェーンにおける露出の変化を浮き彫りにしています。Claude Code、Codex、Gemini、Cursorなどのコーディングエージェントは、人間による確認がほとんどないまま、依存パッケージを自ら選び、インストールし、パッケージのライフサイクルスクリプトを実行できます。

Bloomが数十の組織を対象に測定したところ、エンドポイント1台あたり、エージェントが直接インストールしたパッケージは毎月約70個でした。開発者のマシンでは月に約350個に増えます。

これらの数字には推移的依存関係が含まれていないため、実際の依存関係の規模ははるかに大きい可能性があります。

これは、AIエージェントがこの脆弱性を生み出したという意味ではありません。むしろ、エージェントが被害を増幅させ得るということです。

CVEdatabase access

侵害されたリリースは、マシンの速度で環境に取り込まれる恐れがあります。開発者が依存パッケージの選定に気づいたり、パッケージのリリース履歴を確認したりする前に、取り込まれてしまう可能性もあります。

Bloomは2026年6月6日、GitHubのHackerOneプログラムを通じてこの問題を報告し、6月9日に報告が妥当と確認されたと説明しています。GitHubが緩和策を展開したのは10月2日で、120日以上が経過していました。

npmは現在、検証されていないTrusted Publishingの設定を、作成から48時間後に失効させます。

設定は、最初の公開が成功した時点で検証済みになります。2日間の期間内に使われなければ、その設定ではもうリリースを承認できません。

GitHubによると、この変更により、公開元のIDが検証される前にリポジトリやプロジェクト名の所有権が移るリスクが低減されるということです。

npmはさらに、GitHub Actionsのissue_commentイベントを契機とするTrusted Publishingトークンも拒否します。既存のpull_request_targetに対する制限を補完する措置です。

影響を受けるワークフローを使っているメンテナーは、公開処理をpush、release、workflow_dispatchなど許可されたイベントに移行する必要があります。

メンテナーは、Trusted Publishingの各設定を見直し、紐付けられたGitHubリポジトリが引き続き自らの管理下にあることを確認すべきです。

リポジトリの名称変更、移管、所有者の変更があった場合は、既存の紐付けを削除して作成し直してください。

npmパッケージに紐付いたリポジトリを削除する前には、まずTrusted Publisherの設定を削除または置き換える必要があります。npm trust listを実行すると、設定済みの公開関係を把握できます。

企業の防御担当者にとって、今回の事案は、より広い要件を改めて示しています。AIエージェントを、自律的に動作するソフトウェアの利用者として扱わなければならないという点です。

エージェントがインストールできるパッケージを管理し、postinstallなどのライフサイクルスクリプトを検査し、依存関係の更新を固定またはレビューし、重要度の高い依存関係チェーンで予期しないパッケージのリリースがないかを継続的に監視するといった対策が求められます。

MTTRを21分短縮し、被害が出る前にサイバー脅威を阻止。ANYRUNのSandboxをSOCに統合。

翻訳元: https://gbhackers.com/npm-packages-hijacked/

本記事は gbhackers.com の記事を翻訳・要約したものです。