Microsoftが公開した「Malicious npm packages abuse dependency confusion to profile developer environments」は、Microsoft製品の機能変更や通常の更新プログラムではなく、npmのdependency confusionを悪用したサプライチェーン攻撃に関する公式脅威情報です。結論から言うと、npmを使う組織は、影響スコープの依存関係、.npmrcのレジストリ設定、postinstallなどのインストール時スクリプト、CI/CDや開発端末に保存されたシークレットを優先的に確認する必要があります。
特に注意すべき点は、今回の攻撃が「アプリ実行時」ではなく、npm installのタイミングで動くことです。開発者がコードを読み込まなくても、悪意あるパッケージがインストールされるだけで偵察用ペイロードが実行される可能性があります。Microsoftは、攻撃者が実在企業の内部名前空間に似せたnpmパッケージを公開し、開発者端末やビルド環境からホスト名、環境変数、開発環境の情報を収集していたと説明しています。(Microsoft)
Microsoftの公式情報で示された「変更点」は何か
今回の情報を、Microsoft 365やWindowsのような製品アップデートとして捉えると誤解しやすくなります。実際に変わるのは、ユーザー向け機能ではなく、管理者と開発チームが確認すべきセキュリティ運用の優先順位です。
Microsoftの公式ブログでは、攻撃者が3つのnpmメンテナー名義を使い、複数の組織スコープにまたがって悪意あるパッケージを公開したと説明されています。パッケージは、GitHub Enterprise、Jira、社内ドキュメントポータルのように見えるメタデータをpackage.jsonに設定し、正規の社内パッケージに見えるよう偽装していました。(Microsoft)
管理者や開発者にとっての実務上の変更点は、次の3つです。
| 確認すべき変化 | 実務での意味 | 優先度 |
|---|---|---|
| npmの依存関係確認が必要 | package.jsonだけでなく、package-lock.json、yarn.lock、pnpm-lock.yamlまで確認する | 高 |
.npmrcのスコープ設定が重要 | 社内スコープが公開npmレジストリへ解決されないようにする | 高 |
| インストール時スクリプトの扱いを見直す | postinstallで任意コードが動く前提で、CI/CDや端末の権限を絞る | 高 |
| Defender XDRやプロキシログでの検出 | C2通信、Node.jsプロセス、tmp/cache配下の不審ファイルを探す | 中〜高 |
| シークレットのローテーション | 影響端末・ビルド環境に置かれていたnpmトークン、クラウド資格情報、CI/CDシークレットを再発行する | 高 |
この情報は、単に「悪性npmパッケージが削除されたか」を見るだけでは不十分です。過去にインストール済みの端末、ビルドキャッシュ、生成済みアーティファクト、CI/CDログまで確認する必要があります。
dependency confusionとは何か
dependency confusionは、社内向けに使っているパッケージ名やスコープに似せた、または同じ名前のパッケージを公開レジストリに置き、設定ミスや解決順序の問題を悪用してインストールさせる攻撃です。
たとえば、社内で@mycompany/internal-authという非公開パッケージを使っているとします。本来は社内レジストリから取得すべきですが、.npmrcの設定が不十分だったり、ビルド環境が公開npmレジストリへフォールバックしたりすると、攻撃者が公開npm上に用意した同名・類似名のパッケージを取得してしまう可能性があります。
npmではスコープを特定のレジストリに関連付けられます。公式ドキュメントでも、npm config set @myco:registry http://reg.example.comのようにスコープとレジストリを関連付けると、そのスコープのパッケージインストールは指定レジストリへ向かうと説明されています。 (npm ドキュメント)
つまり、今回のような攻撃への基本対策は、「社内っぽい名前のパッケージを信用しない」だけではありません。社内スコープが必ず社内レジストリに解決される設定になっているかを確認することが重要です。
今回の攻撃チェーン
Microsoftが説明する攻撃チェーンは、npmを使う開発現場にとって非常に現実的です。攻撃は、被害者がアプリを起動したタイミングではなく、依存関係をインストールするタイミングで成立します。
| 段階 | 攻撃内容 | 確認ポイント |
|---|---|---|
| パッケージ公開 | 攻撃者が実在企業の内部名前空間に似たスコープでnpmパッケージを公開 | 自社スコープと似た公開パッケージがないか |
| 信頼させる偽装 | repository、homepage、bugsなどを社内GitHub、Jira、Docs風に設定 | package.jsonのメタデータが実在するか |
| 自動実行 | postinstallフックでnode scripts/postinstall.jsを実行 | install時スクリプトを許可していないか |
| ペイロード取得 | C2サーバーからOS別のペイロードを取得 | 外向き通信ログを確認 |
| 端末偵察 | ホスト名、環境変数、開発者コンテキストなどを収集 | 環境変数に秘密情報を置いていないか |
| 追跡回避 | cacheディレクトリやrun-onceマーカーで繰り返し実行を抑制 | ~/.cacheやtmp配下の不審ファイルを探す |
Microsoftによると、実行の流れはnpm installからpostinstall、難読化されたpostinstall.js、C2へのHTTPS GET、tmpディレクトリへの書き込み、バックグラウンドプロセス起動へ進みます。さらに、ペイロードはWindows、macOS、Linux向けに分岐していました。(Microsoft)
重要なのは、攻撃が「偵察のみ」に見える点です。Microsoftは、今回のキャンペーンで*_RECON_ONLY=1が使われ、環境情報の収集を主目的としていた一方、設計上は後続攻撃で認証情報の窃取やバックドア設置へ進める余地があると説明しています。(Microsoft)
影響範囲:Microsoft利用者全員ではなく、npmを使う開発・ビルド環境が中心
この情報はMicrosoft Security Blogで公開されていますが、影響を受ける可能性が高いのは、Microsoft製品の一般利用者ではありません。主な対象は、npmを利用する開発者、フロントエンド開発チーム、Node.jsを含むビルドパイプライン、CI/CD環境です。
特に、次の条件に当てはまる組織は優先して確認してください。
| 確認対象 | 該当するケース | リスク |
|---|---|---|
| 開発者端末 | ローカルでnpm installやnpm ciを実行している | 端末上の環境変数やトークンが露出する可能性 |
| CI/CD runner | GitHub Actions、Azure Pipelines、Jenkinsなどでnpm installを実行している | ビルド用シークレットやクラウド資格情報が狙われる可能性 |
| 社内npmレジストリ利用環境 | private registry、proxy registry、artifact feedを使っている | 公開npmへのフォールバック設定があるとdependency confusionが成立しやすい |
| lockfileを自動更新する運用 | Renovate、Dependabot、手動更新などで依存関係を頻繁に更新する | 高いバージョン番号の悪性パッケージを取り込む可能性 |
| 環境変数にシークレットを置く運用 | NPM_TOKEN、クラウドキー、CI/CDトークンを環境変数で渡している | 偵察ペイロードから見える可能性 |
Microsoftは、影響確認の対象として、9つのスコープを挙げています。確認時は、直接依存だけでなく推移的依存、lockfile、ビルドログも対象にします。(Microsoft)
@cloudplatform-single-spa
@wb-track
@data-science
@ce-rwb
@payments-widget
@travel-autotests
@t-in-one
@capibar.chat
@sber-ecom-core
なお、要約では「33個の悪意あるnpmパッケージ」と表現されることがありますが、Microsoftの本文では5月28日の26件と7件に加え、5月29日のt-in-one関連の波も説明されています。実務では件数だけで判断せず、上記スコープ全体を検索対象にしてください。(Microsoft)
管理者が最初に確認すべきこと
まずは、影響を受けた可能性のあるリポジトリ、端末、CI/CD実行環境を洗い出します。いきなり全シークレットをローテーションする前に、どこで該当スコープが参照されたかを確認すると、対応範囲を絞りやすくなります。
リポジトリとlockfileを検索する
Git管理下のリポジトリでは、package.jsonだけでなくlockfileも検索します。lockfileには、開発者が意識していない推移的依存や、実際に解決されたバージョンが残っている場合があります。
rg '@cloudplatform-single-spa/|@wb-track/|@data-science/|@ce-rwb/|@payments-widget/|@travel-autotests/|@t-in-one/|@capibar\.chat/|@sber-ecom-core/' \
package.json package-lock.json yarn.lock pnpm-lock.yaml .npmrc
Windows PowerShellで確認する場合は、次のように検索できます。
Get-ChildItem -Recurse -Include package.json,package-lock.json,yarn.lock,pnpm-lock.yaml,.npmrc |
Select-String -Pattern '@cloudplatform-single-spa/|@wb-track/|@data-science/|@ce-rwb/|@payments-widget/|@travel-autotests/|@t-in-one/|@capibar\.chat/|@sber-ecom-core/'
該当が見つかった場合は、単に削除するだけでなく、次の情報を記録します。
| 記録する情報 | 理由 |
|---|---|
| リポジトリ名・ブランチ | 影響範囲を特定するため |
| 該当ファイル | 直接依存か、lockfileだけかを切り分けるため |
| バージョン | Microsoftが示す悪性バージョンと照合するため |
| install実行日時 | 2026年5月28日以降の実行有無を確認するため |
| 実行環境 | 開発端末かCI/CDかで対応が変わるため |
Microsoftは、2026年5月28日以降に該当パッケージをインストールまたはビルドしたシステムを特定するよう推奨しています。また、@capibar.chat/ui-kitと@sber-ecom-core/sberpay-widgetについては、2026年5月4日の事前公開版にも注意が必要としています。(Microsoft)
npmの依存ツリーを確認する
該当リポジトリで、依存ツリーに含まれているかを確認します。
npm ls --all | grep -E '@cloudplatform-single-spa|@wb-track|@data-science|@ce-rwb|@payments-widget|@travel-autotests|@t-in-one|@capibar.chat|@sber-ecom-core'
PowerShellでは次のように確認できます。
npm ls --all | Select-String -Pattern '@cloudplatform-single-spa|@wb-track|@data-science|@ce-rwb|@payments-widget|@travel-autotests|@t-in-one|@capibar.chat|@sber-ecom-core'
ただし、npm lsは現在のnode_modulesに依存します。過去にCI/CDで一度だけインストールされたケースや、コンテナイメージ内に残っているケースは見落としやすいため、lockfile、ビルドログ、アーティファクトの確認も併用してください。
.npmrcで確認すべき設定
dependency confusion対策の要は、社内スコープを公開npmへ解決させないことです。npm公式ドキュメントでは、.npmrcはプロジェクト、ユーザー、グローバル、組み込み設定の順に扱われ、プロジェクトルートの.npmrcでプロジェクト固有の設定を行えると説明されています。(npm ドキュメント)
自社の内部パッケージスコープがある場合は、プロジェクト直下の.npmrcに明示的なレジストリ設定を置くのが基本です。
@your-org:registry=https://registry.example.com/npm/
//registry.example.com/npm/:_authToken=${NPM_TOKEN}
悪い例は、社内スコープを明示せず、デフォルトレジストリだけに依存している設定です。
registry=https://registry.npmjs.org/
この状態では、社内向けに見えるスコープでも、設定や環境によって公開npmへ解決される余地があります。特に複数のレジストリを使う組織では、ローカル端末、CI/CD、Dockerfile、開発コンテナ、社内テンプレートの.npmrcが一致しているかを確認してください。
.npmrcのチェックポイント
| チェック項目 | OKの状態 | 注意が必要な状態 |
|---|---|---|
| 社内スコープのregistry指定 | @your-org:registry=...がある | デフォルトregistryだけ |
| 認証トークンのスコープ | レジストリURLに紐付いている | _authToken=...が単独で書かれている |
| CI/CDの設定 | パイプライン内でも同じ.npmrcを使用 | ローカルだけ安全でCI/CDは別設定 |
| Dockerビルド | build stageに必要最小限のトークンだけ渡す | トークンをイメージレイヤーに残す |
| lockfileのresolved | 想定する社内レジストリを指す | 社内スコープなのにregistry.npmjs.orgを指す |
npm公式ドキュメントでも、認証関連の設定は特定レジストリにスコープする必要があり、そうすることで誤ったホストへ資格情報を送らないようにすると説明されています。(npm ドキュメント)
postinstallを前提にした安全な展開方法
今回の攻撃で特に危険なのは、postinstallによる自動実行です。Microsoftは、すべてのパッケージがpackage.jsonでpostinstallフックを宣言し、被害者がnpm installを実行した時点で悪意あるコードが実行されると説明しています。(Microsoft)
npmには、package.json内のスクリプト実行を抑止するignore-scripts設定があります。npm公式ドキュメントでは、ignore-scriptsがtrueの場合、package.jsonに指定されたスクリプトを実行しないと説明されています。ただし、npm startやnpm testなど、特定スクリプトの実行を明示するコマンドは対象スクリプト自体を実行します。(npm ドキュメント)
実務では、すべての環境でいきなりignore-scripts=trueにすると、ネイティブモジュールやビルド後生成物に依存するパッケージが壊れることがあります。そのため、次のように段階導入するのが現実的です。
| 導入段階 | 実施内容 | 目的 |
|---|---|---|
| 監査フェーズ | CIでnpm ci --ignore-scriptsを試す | どのパッケージがinstall scriptに依存しているか把握する |
| 例外整理 | 必要なパッケージだけ理由付きで許可する | 「何となくpostinstallを許可」を避ける |
| 本番導入 | 新規・外部由来の依存更新時は--ignore-scriptsを標準にする | 未検証パッケージの自動実行を防ぐ |
| 継続運用 | lockfile差分とpackage.jsonのscripts差分をレビュー対象にする | 依存更新時の見落としを減らす |
一時的に個別コマンドで抑止するなら、次のように実行できます。
npm ci --ignore-scripts
ユーザーまたはCI/CD環境全体で既定値にする場合は、影響を検証したうえで設定します。
npm config set ignore-scripts true
npm config get ignore-scripts
注意点は、ignore-scriptsを有効にしただけで安全が完成するわけではないことです。信頼済みとして例外許可したパッケージのpostinstallが侵害されれば、同じリスクが戻ります。例外はリスト化し、なぜ必要なのか、誰が承認したのか、いつ見直すのかを決めておくべきです。
Microsoft Defenderで確認すべき検出ポイント
Microsoftは、Microsoft Defender Antivirusが難読化されたpostinstallステージャーや偵察ペイロードを検出・ブロックすること、Microsoft Defender for Endpointがnpm lifecycle script abuseやDetached child processの挙動検出を提供することを説明しています。(Microsoft)
Defender XDRを利用している場合は、次の観点でハンティングすると実務に落とし込みやすくなります。
| 観点 | 探すもの | 意味 |
|---|---|---|
| プロセス | node.exe、npm.exe、npx.exeからのpostinstall実行 | インストール時スクリプト悪用の可能性 |
| ネットワーク | oob.moika[.]techや関連ルアードメインへの通信 | C2または偽装インフラへの接続可能性 |
| ファイル | ._*_init.js、~/.cache/._t-in-one_init/など | ペイロードや実行済みマーカーの可能性 |
| ヘッダー | X-Secretの固定値 | キャンペーン固有の高精度IOC |
| 環境変数 | *_RECON_ONLY、*_PKG、*_VER、*_SECRET | 偵察ペイロードの実行痕跡 |
Microsoftが示すIOCには、C2サーバーoob.moika[.]tech、OS別ペイロードURL、scripts/postinstall.js、._cloudplatform-single-spa_init.js、._wb-track_init.js、._t-in-one_init.js、~/.cache/._t-in-one_init/、固定のX-Secretヘッダー値などが含まれます。(Microsoft)
Defender XDRの簡易ハンティング例
まずはネットワーク通信を確認します。
DeviceNetworkEvents
| where Timestamp > ago(30d)
| where RemoteUrl has_any ("oob.moika.tech", "npm.t-in-one.io", "docs.t-in-one.io", "jira.t-in-one.io")
| project Timestamp, DeviceName, RemoteUrl, RemoteIP, RemotePort,
InitiatingProcessFileName, InitiatingProcessCommandLine, AccountName
次に、npmやNode.jsのプロセスから不審なインストール時スクリプトが動いていないかを確認します。
DeviceProcessEvents
| where Timestamp > ago(30d)
| where FileName in~ ("node.exe", "npm.cmd", "npm.exe", "npx.cmd", "npx.exe")
| where ProcessCommandLine has_any ("preinstall", "postinstall", "install")
| where ProcessCommandLine has_any (
"@cloudplatform-single-spa", "@wb-track", "@data-science",
"@ce-rwb", "@payments-widget", "@travel-autotests",
"@t-in-one", "@capibar.chat", "@sber-ecom-core")
| project Timestamp, DeviceName, FileName, ProcessCommandLine,
InitiatingProcessFileName, InitiatingProcessCommandLine, AccountName
tmpやcache配下のファイル作成も確認します。
DeviceFileEvents
| where Timestamp > ago(30d)
| where FileName matches regex @"^\._.*_init\.js$"
or FolderPath has_any (
".cache/._cloudplatform-single-spa_init",
".cache/._wb-track_init",
".cache/._t-in-one_init")
| project Timestamp, DeviceName, FolderPath, FileName, ActionType,
InitiatingProcessFileName, InitiatingProcessCommandLine
Microsoftのサンプルでは7日間の検索例が示されていますが、過去のビルドや開発端末を広く確認する場合は、ログ保持期間に応じて30日程度まで広げると見落としを減らせます。(Microsoft)
シークレットとトークンのローテーション判断
今回のペイロードは偵察目的と説明されていますが、環境変数や開発者コンテキストを収集する設計である以上、影響環境に置かれていたシークレットは「見られた可能性がある」と考えて扱うべきです。
特に、次の情報は優先的にローテーションします。
| 対象 | 例 | 対応 |
|---|---|---|
| npmトークン | NPM_TOKEN、publish token | 再発行し、古いトークンを失効 |
| CI/CDシークレット | GitHub Actions Secrets、Azure Pipelines変数、Jenkins credentials | 影響ジョブで使われたものから優先 |
| クラウド資格情報 | AWS、Azure、GCPのアクセスキーやサービスプリンシパル | 権限範囲を確認し、必要に応じて再発行 |
| Git関連トークン | GitHub PAT、GitLab tokenなど | 最終使用履歴を確認してローテーション |
| 社内APIキー | ステージング、本番APIキー | 環境ごとに影響を切り分ける |
ローテーション時に失敗しやすいのは、「該当パッケージを消したから大丈夫」と判断してしまうことです。攻撃者が収集した情報は、パッケージ削除後も悪用される可能性があります。該当環境でnpm installが実行された日時、保存されていた環境変数、CI/CDで使用された権限をセットで確認してください。
CI/CDで見落としやすい注意点
今回の攻撃では、CI環境を検出して実行を回避する処理も説明されています。Microsoftによると、ステージャーはCI環境変数やスコープ固有の変数を確認し、検出時に静かに終了することで、監視が強いCI/CD上での発見を避ける狙いがありました。(Microsoft)
そのため、「CIログに怪しい通信がない」だけでは安全とは言い切れません。次のように確認範囲を広げる必要があります。
| 見落としやすい場所 | 確認内容 |
|---|---|
| 開発者端末 | ローカルでnpm installを実行していないか |
| 一時的な検証環境 | PoCや検証ブランチで依存更新を試していないか |
| コンテナビルド | Docker build中にトークンが渡されていないか |
| キャッシュ | npm cache、CI cache、Docker layerに悪性パッケージが残っていないか |
| フォーク・ブランチ | main以外のブランチでlockfileが更新されていないか |
CI/CDでは、ビルド成功だけを見ず、依存解決のログ、外向き通信、使用されたシークレットの範囲まで確認します。とくに本番デプロイ権限を持つrunnerでnpm installを行っている場合は、影響調査を優先してください。
開発チームに展開する際の実務ポイント
セキュリティ担当者が一方的に「npm installを禁止」と伝えるだけでは、現場の開発が止まり、迂回運用が生まれます。展開時は、禁止ではなくルール化が重要です。
依存関係更新のレビュー基準を決める
依存関係の更新PRでは、次の差分をレビュー対象にします。
| レビュー対象 | 見るべきポイント |
|---|---|
| 新規スコープ | 自社・取引先・有名サービスに似た名前ではないか |
| バージョン番号 | 不自然に高いバージョンになっていないか |
scripts | preinstall、install、postinstallが追加されていないか |
resolved | lockfileが想定レジストリを指しているか |
| メンテナー情報 | 急に変わっていないか、公開直後ではないか |
| READMEやURL | 社内風URLを装っていないか、実在確認できるか |
Microsoftは、攻撃者が100.100.100のような不自然に高いバージョン番号を使い、依存解決で正規の内部パッケージより優先されることを狙ったと説明しています。(Microsoft)
開発者に伝えるべき判断基準
開発者向けには、次のように具体的に伝えると行動につながります。
| 開発者が見るもの | 危険なサイン |
|---|---|
| パッケージ名 | 自社・取引先・金融・認証・token・secretを連想させる名前 |
| バージョン | 99.0.7、100.100.100のような極端に高い番号 |
| install script | postinstallで外部通信や難読化JSを実行 |
| メタデータ | GitHub Enterprise、Jira、Docs風だが実在確認できないURL |
| 公開日 | 直近に公開されたばかりで利用実績が少ない |
ポイントは、「有名そうに見える」「社内ツールっぽい」ことを信用材料にしないことです。今回の攻撃では、まさにその心理が狙われています。
すぐ実施したい対応チェックリスト
最後に、管理者と開発者がすぐ使えるチェックリストに整理します。
| 対応 | 担当 | 完了条件 |
|---|---|---|
| 影響スコープを全リポジトリで検索 | 開発・SRE | package/lockfile/.npmrcの検索結果を記録 |
| CI/CDログを確認 | SRE・DevOps | 2026年5月28日以降のnpm install履歴を確認 |
.npmrcを棚卸し | 開発基盤チーム | 社内スコープが社内レジストリへ固定されている |
| 外向き通信ログを確認 | セキュリティ運用 | C2・ルアードメインへの通信有無を確認 |
| tmp/cache配下を確認 | 情シス・SOC | ._*_init.jsやrun-once markerの有無を確認 |
| シークレットをローテーション | 各システム管理者 | 影響環境のトークン・クラウド資格情報を再発行 |
ignore-scripts導入を検証 | 開発基盤チーム | 壊れるパッケージと例外許可をリスト化 |
| 依存更新レビューを強化 | 開発チーム | 新規スコープ、install script、resolved先をレビュー項目化 |
今回の「Malicious npm packages abuse dependency confusion to profile developer environments」は、Microsoft製品の設定変更というより、npmを使う開発組織に向けた強い警告です。最初にやるべきことは、影響スコープの検索、.npmrcのスコープ固定、CI/CDと開発端末のログ確認です。そのうえで、該当環境に置かれていたシークレットをローテーションし、postinstallを無条件に許可しない運用へ移行してください。

コメント