SLSA(Supply-chain Levels for Software Artifacts)プロベナンスチェックは、パッケージのビルド元と改ざんがないことを証明する仕組みとして広く採用されてきた。だがこの前提は、2026年5月19日の攻撃で破られた。TeamPCPと帰属されるグループが展開した「Mini Shai-Hulud」ワームは、有効なSLSAプロベナンス証明書を持つ状態で323のパッケージに侵入し、署名証明書はビルドの正規性を保証するが、ビルドへの入力が汚染されていないことは保証しないという事実を実証した。GitHubは攻撃翌日の5月20日、npm v11.15.0でStaged Publishing機能を実装した。npm stage publishでステージング、npm stage approveでMFA承認という2段階ゲートで公開フローを保護する仕組みだ。だが、MFA登録済みの攻撃者がメンテナーアカウントを侵害している場合、このゲートは機能しない根本的な限界が残っている。

AD

GitHub Actionsキャッシュを橋にした感染の連鎖

Mini Shai-Hulud攻撃の核心は、GitHub Actionspull_request_targetワークフローとキャッシュ機構の組み合わせにある。通常のプルリクエストはフォーク元リポジトリのシークレットにアクセスできないよう制限されているが、pull_request_targetはターゲットリポジトリのコンテキストで実行されるため、シークレットへのアクセス権を持つ。この設計上の特性を悪用し、TeamPCPは@atoolメンテナーアカウントを侵害した後、フォークリポジトリ経由でワークフローをトリガーした。

実際の感染経路は次のように機能した。攻撃者はターゲットリポジトリへのフォークを作成し、悪意あるコードを含むプルリクエストを送る。pull_request_targetワークフローが起動すると、攻撃者のコードがターゲットのコンテキストで実行され、GitHub Actionsのキャッシュに悪意あるpnpmストアを挿入する。以降のビルドではキャッシュが優先的に使用されるため、汚染されたpnpmストアから悪意あるパッケージが展開される。最終的にnpmレジストリへの公開権限を持つシークレットが窃取され、汚染バージョンがレジストリに直接アップロードされた。

StepSecurityはこの攻撃について「SLSAビルドレベル3証明書を持つパッケージへの初のサプライチェーン攻撃であり、プロベナンスチェックの限界を示した」と報告している。感染パッケージが有効な署名証明書とSLSAプロベナンスを保持していたのは、ビルド自体は正規の環境で実行されているからだ。問題はビルド環境に流入する依存関係が汚染されていたという点であり、「正規のビルドプロセスを通した悪意あるコード」という構図はスキャンベースの検出を意味的に難しくする。

22分で1,600万DLを汚染、dead-man's switchが開発者を縛った理由

2026年5月19日、TeamPCPは22分間の自動化バーストで323パッケージ・639の悪意あるバージョンをnpmレジストリに公開した。被害を受けたパッケージの合計週間ダウンロード数は約1,600万に達し、echarts-for-react(週間約110万DL)もその中に含まれていた。同日、Microsoft durabletask Python SDK(月間40万DL超)もPyPI上で汚染され、35分間で悪意あるバージョンが公開された。

マルウェアの設計で特に注目されるのがdead-man's switchの実装だ。感染後、マルウェアは「IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner」という名称のGitHubトークンを生成し、60秒ごとにapi.github.com/userをポーリングする。トークンが失効した場合、マルウェアはUnix系環境でrm -rf ~/を実行してホームディレクトリを消去する。このトークン名は脅迫の意図を名称そのものに刻み込んだものであり、セキュリティチームがインシデント対応としてトークンを無効化しようとすると、被害者のマシンデータが同時に失われるというジレンマを意図的に設計している。

認証情報窃取の範囲も広い。AWS、Azure、GCP、Kubernetes、HashiCorp Vault、Docker、Terraform、GitHubを含む90以上の開発ツールの設定ファイルが対象とされた。また、ペイロードはロシア語ロケールのシステムをスキップする設計になっており、攻撃対象を意図的に絞り込んでいることがわかる。TeamPCPは民間セキュリティ企業による帰属であり、政府機関による公式確認はないが、2025年9月の前波で500以上のパッケージを汚染した実績に加え、Aqua Security Trivyスキャナー(2026年3月)やBitwarden CLI(2026年4月)への攻撃も同グループとされている。

AD

Staged Publishingの仕組み:ステージングから承認まで

GitHubは攻撃翌日の2026年5月20日、npm CLI v11.15.0でStaged Publishingを含む複数のセキュリティ機能を発表した。本機能は2020年から議論されていたRFC #92がベースであり、攻撃を受けて緊急実装に踏み切った形だ。Node 22.14.0以上の環境で利用でき、既にレジストリに存在するパッケージに限定される(新規パッケージへの適用は不可)。

公開フローは2段階に分割される。まずnpm stage publishコマンドを実行すると、パッケージがステージング状態でレジストリに登録される。この段階では2FAは不要で、CIパイプラインからの自動実行も想定している。次にnpm stage approve <stage-id>コマンドを別途実行し、MFA(多要素認証)による承認を行うことで初めてパッケージが公開される。承認ステップは手動操作が前提となっており、CIが自動的にステージングを上げることを意図的に阻んでいる。

この設計が解消しようとしているのは、侵害されたCI環境が直接npmレジストリへの公開権限を持つ状況だ。攻撃者がGitHub Actionsのシークレットを窃取してもステージングまでしか進めず、承認には別チャネルでのMFA操作が必要になる。Staged Publishing以外にも、OIDC一括オンボーディング(Trusted Publishing)とclassicトークンの廃止が同時にアナウンスされており、レジストリへのアクセス認証全体の再設計を意図した動きだ。

防御の限界と、CI/CDパイプラインに残る課題

GitHub自身も認めているように、メンテナーアカウントを侵害されMFA登録済みの攻撃者には、Staged Publishingは無効だ。今回の@atoolアカウント侵害がどの経路で行われたかによって、Staged Publishingが今回の攻撃を止められたかどうかも変わる。完全自動化CI/CDを前提としている組織にとっても無視できない問題がある。Vercel、Netlify、GitHub Actionsをベースにした公開フローでは、人間の介在なくnpm公開まで完走することを前提としているケースが多く、Staged Publishingのワークフローを導入すると、承認ステップのために誰かが手動でコマンドを実行する必要が生じ、完全自動化の前提が崩れる。

特に小規模チームやOSSプロジェクトでは、リリースのたびにMFA承認を行う担当者を用意することが現実的でないケースもある。Staged Publishingは理想的な防御アーキテクチャを示している一方で、実装の障壁が高く、採用できない組織が多数残ることになる。つまり、業界全体の防御水準を底上げする解決策にはなっていない。

スキャンベースの防御にも構造的な問題が残る。今回の攻撃が示したように、有効なSLSAプロベナンスと署名証明書を持つパッケージは、従来の検証フローでは「安全」と判断される。SnykやSocket.devが提供する行動分析型の検出やランタイム依存関係の監視は補完的な防衛として機能するが、Staged Publishingと組み合わせてはじめて実効的な多層防御になる。証明書を信頼するのではなく、公開フロー自体に承認ゲートを挿入するというアプローチは、供給チェーンセキュリティの重心を「事後検出」から「事前ゲーティング」へと移すものだ。

AD

開発者がすぐ取るべき対応

npm v11.15.0へのアップデートは即座に行うべきだが、それだけでは不十分だ。まず依存関係の監査として、npm auditでフラグされていない場合でも、2026年5月19日前後のバージョンに更新されたパッケージを手動で確認する必要がある。特にSLSAプロベナンスが存在するから安全だという判断は、今回の攻撃以降は根拠を失っている。

認証情報ローテーションも優先度が高い。AWS、Azure、GCP、GitHubのトークンを含む開発環境の認証情報を点検し、不審な長期トークンが存在しないか確認する。「IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner」という名前のトークンが存在する場合は感染の可能性が高い。ただし、dead-man's switchの仕組みから、単純なトークン失効では連鎖的な被害が生じるリスクがあるため、対応にはセキュリティ専門家の関与が望ましい。

GitHub Actionsのワークフローにおけるpull_request_targetの使用も見直しが必要だ。このワークフロートリガーはフォークからのシークレットアクセスを可能にするため、必要性を精査した上でシークレットへのアクセス範囲を最小化する設計に切り替えることが推奨される。Staged Publishingの導入時は、CI/CDパイプラインの自動公開フローを見直し、承認ステップを誰がどのように担うかを事前に設計する必要がある。今回の攻撃が問いかけているのは、「自動化の利便性」とそこに内在するリスクの間のトレードオフを、各組織が明示的に判断しているかどうかという点だ。