2026年6月1日、Red Hatが管理するnpmスコープ @redhat-cloud-services の31パッケージ・60超バージョンが侵害された。Microsoft Threat Intelligenceが公開警告を発し、Wiz Researchはこのマルウェアを「Miasma」と命名した。インストール時に自動実行され、npm・GitHub・AWS・SSHを含む多種の認証情報を窃取して自己増殖する、Mini Shai-Hulud系の亜種である。
npmサプライチェーン攻撃全体の防御フレームワークと恒久対策についてはサプライチェーンセキュリティ完全ガイド2026|攻撃手法・防御ツール・実践チェックリストをご覧ください。
30秒で理解する
- ・2026-06-01、
@redhat-cloud-servicesスコープのnpm 31パッケージ・60超バージョンが侵害された。 - ・
preinstallフックでBunを取得し、ROT-21復号evalで認証情報(npm/GitHub/AWS/SSH/GCP/Azure/Vault等)を窃取する。 - ・Wizが「Miasma」と命名。Mini Shai-Hulud系亜種で、ツール一式はTeamPCPが公開(OSS化)済み。
- ・侵入口は個人アカウントではなくRed Hat従業員のGitHub/CI。OIDC+SLSA署名付きで正規publishルートが悪用された。
- ・該当版を導入済みなら侵害前提で全シークレットを即ローテ、信頼できる旧版へrevert、当該版をブロックする。
ツイート本文と独立解析には数値の食い違いがある。本記事は独立解析側を採用している(後述)。
何が起きたか――Microsoftの警告と一次解析の整合
時刻はすべてUTC。Microsoftの公開警告を起点に、Wiz・StepSecurity・Aikido・Red Hat公式の一次解析を突き合わせて整理する。
| 日時 (UTC) | 出来事 |
|---|---|
| 2026-06-01 10:53:06〜10:53:33 | 第1波の悪性コミット/publish |
| 2026-06-01 13:44:48〜13:46:47 | 第2波の悪性コミット/publish |
| 2026-06-01 | Wiz Researchが侵害を検知し「Miasma」と命名 |
| 2026-06-01 | StepSecurity・Aikido等が個別解析を公開 |
| 2026-06-01 | RedHatInsights公式GitHub IssueでSecurityアラート |
| 2026-06-01 | Microsoft Threat Intelligenceが公開警告を発出 |
侵害は1日のうちに2波に分かれて実行された。第1波・第2波とも数十秒〜2分程度の短いバーストで、自動化スクリプトによるpublishと考えられる。
侵害された@redhat-cloud-servicesスコープは、Red Hatのクラウドサービス向けフロントエンドコンポーネント・APIクライアント・開発ツーリングを多数含む。広く再利用される性質上、影響範囲が読みにくい。
- ・Microsoftのツイートは「90+パッケージ」「ROT-9 evalローダー」と記載している。
- ・一方、Wiz・StepSecurity・Aikido・Red Hat公式Issueの独立解析では「31パッケージ・60超バージョン」で一致する。
- ・難読化方式も、StepSecurityの詳細リバースエンジニアリングではROT-21(Wiz/Aikidoは「ROT系」とのみ記載)。ROT-9と言及したソースは確認できなかった。
- ・本記事は誤情報の拡散を避けるため解析側(31/ROT-21)を正として記述する。
Microsoftの警告は世界中の防御者向けに即時性を優先した速報であり、後続の詳細解析と細部が一致しないことは珍しくない。引用時は数値の出所を明示するのが安全だ。
同系統のワームが直前に別エコシステムを襲った経緯は@antv npmに不正コード混入|Mini Shai-HuludがAnt Design可視化323パッケージを22分で汚染にまとまっている。
技術的詳細:自己増殖ワーム「Miasma」の動作
攻撃チェーンは「preinstallフック起動 → Bun経由でペイロード実行 → 認証情報スキャン → 流出 → 再publishによる自己増殖」という流れだ。
2026-06-01"] -->|"ci.yaml ワークフロー改変"| B["npm Registry
31パッケージ 60超バージョン
OIDC+SLSA署名付きで正規publish"] B -->|"npm install 実行"| C["開発者PC または CI/CD環境"] C -->|"preinstall hook 起動"| D["index.js 実行
約8KB → 4.2MB に肥大化"] D -->|"ROT-21復号 + eval()
try-catchで沈黙"| E["oven-sh/setup-bun でBun導入
_index.js 実行(EDR回避)"] E --> F["認証情報スキャン
npm/GitHub/AWS/SSH/GCP/Azure/Vault 等"] E -->|"npmトークン窃取"| G["被害者管理パッケージへ
同一ペイロード再注入・再publish"] G -->|"自己増殖"| B
Step 1 — preinstallフックによる実行
各悪性パッケージのpackage.jsonに"preinstall": "node index.js"が追加されている。
npm installを実行すると、アプリケーションコードより前に、このフックが自動で発火する。
Step 2 — index.jsの肥大化と難読化
正規では数KB程度のindex.jsが、約4.2MBに肥大化していた。
中身はROT-21(シーザー暗号系)で難読化され、文字コードの数値配列をString.fromCharCodeで実行時に復元する。
復号した本体はtry { eval(...) } catch(e) {}の沈黙エラーハンドリングで実行される。失敗しても痕跡を残さない設計だ。
Step 3 — Bun経由のペイロード実行(EDR回避)
ペイロードはCIワークフロー内でoven-sh/setup-bunを使ってBunを導入し、_index.jsを実行する。
Node.js前提の監視やEDRシグネチャを、別ランタイムへ逃げることで回避する狙いだ。Bun自体に脆弱性はない。
Step 4 — 認証情報スキャン(窃取対象は広い)
ツイートはnpm/GitHub/AWS/SSHの4種を挙げるが、一次解析では対象がさらに広い。
- ・GitHub:
GITHUB_TOKEN、ACTIONS_RUNTIME_TOKEN、GitHub ActionsのisSecret:trueシークレット(プロセスメモリから抽出)。 - ・AWS: アクセスキー、
~/.aws/credentials。 - ・クラウド全般: GCPサービスアカウント、Azureサービスプリンシパル、Kubernetes(kubeconfig)。
- ・シークレット管理: HashiCorp Vaultトークン、CircleCIトークン。
- ・開発者環境: npmトークン、SSH秘密鍵、Docker認証、GPG鍵、
.env。
Step 5 — 自己増殖(ワーム化)
窃取したnpmトークンで、被害者が管理する他パッケージを列挙する。
それらに同一ペイロードを再注入してバージョンを上げ、再publishする。初期標的を超えて被害が連鎖する仕組みだ。
TanStackを襲った同系ワームの挙動はTanStack公式@tanstack/*にマルウェア混入|Mini Shai-Huludワームも参照してほしい。
なぜ署名があったのに侵害できたのか
今回の核心は「正規の署名付きルートが乗っ取られた」点にある。
- 侵入口は個人のnpmアカウント窃取ではなく、Red Hat従業員のGitHubアカウント/CIだった。
- 攻撃者は
ci.yamlワークフローを改変し、OIDC+SLSA provenance(来歴署名)付きで正規publishルートからパッケージを公開した。 - つまり「署名は正規に通った」。署名検証だけでは弾けない。
SLSA provenanceが保証するのは「誰が・どのCIから publish したか」であって、「中身が安全か」ではない。
publish主体そのものが乗っ取られると、署名は攻撃者に味方してしまう。
教訓は明確だ。「署名=安全」ではない。CIのpublish経路そのものが急所であり、署名(誰が)に加えて中身(何を)を検証するSCAとポリシー強制が要る。
影響範囲
侵害された主なパッケージとバージョンは以下のとおり(Wiz・StepSecurity・公式Issueで確認できたもの)。
| パッケージ | 侵害が確認されたバージョン例 |
|---|---|
@redhat-cloud-services/rbac-client |
9.0.3 / 9.0.4 / 9.0.6 |
@redhat-cloud-services/frontend-components |
7.7.2 / 7.7.3 / 7.7.5 |
@redhat-cloud-services/host-inventory-client |
5.0.3 / 5.0.4 / 5.0.6 |
@redhat-cloud-services/chrome |
2.3.1 / 2.3.2 / 2.3.4 |
@redhat-cloud-services/compliance-client |
4.0.3 / 4.0.4 / 4.0.6 |
@redhat-cloud-services/topological-inventory-client |
3.0.10 / 3.0.11 / 3.0.13 |
@redhat-cloud-services/types |
3.6.1 / 3.6.2 / 3.6.4 |
Microsoftのツイートは加えてpatch-client 4.0.4・insights-client 4.0.4も名指ししている。
確定リストは時間とともに更新されるため、公式GitHub Issueとベンダーの解析を必ず一次で確認してほしい。
- ・Red Hatは「Red Hat製品・エンタープライズ製品には、いずれの侵害版も混入・出荷されていない」と表明している。
- ・理由はエンジニアリングチームによるバージョンピン留めの徹底。
- ・つまり「Red Hat製品経由のリスク」は公式に否定されている。影響を受けるのは、当該スコープへ直接依存する自社開発側だ。
過度に不安を煽る必要はない。一方で、当該スコープを直接依存に持つフロントエンド/データ基盤チームは確認が必要だ。
いま開発者がやること
検知
まず、依存ツリーに当該スコープが含まれるか、lockファイルで確認する。
# lockファイルで @redhat-cloud-services を確認
grep -E '@redhat-cloud-services/' \
package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null
次に、lifecycle scriptと巨大なindex.jsという2つの検知パターンを探す。
# 悪性のlifecycleフックを持つpackage.jsonを検索
find node_modules -name package.json \
-not -path "*/node_modules/*/node_modules/*" \
-exec grep -lE '"(pre|post)?install"\s*:\s*"node index\.js"' {} \;
# 想定外に巨大なindex.js(KB想定が数MB)をフラグ(4.2MBが目安)
find node_modules -name index.js -size +1M -type f
さらに、難読化パターンとCIログを確認する。
- ROT復号後に
eval()を呼ぶコード、try{...}catch(e){}の沈黙ハンドリング。 String.fromCharCodeで数値配列を実行時復元するパターン。- CIログで
oven-sh/setup-bunなど予期しないランタイム導入が出ていないか。
# node_modules内の難読化シグネチャを横断検索
grep -rlE "String\.fromCharCode|oven-sh/setup-bun" node_modules \
--include="*.js" 2>/dev/null | head
- ・「巨大なindex.js(サイズ急増)+lifecycleフック+ROT復号eval+silent catch」を複合シグネチャとして検知する。
- ・単一指標(例: evalの有無)だけでは誤検知が多い。組み合わせで精度を上げる。
- ・publish直後の新バージョンは、lockファイルのdiffレビューを必須化する。
- ・本記事ではIoC(C2アカウント名・ドメイン等)は意図的に掲載していない。ブロックリストは誤適用リスクがあるため、必ず一次ソースで再確認すること。
対応(侵害が疑われる場合)
順序を誤らないこと。まず認証情報のローテーション、その後にクリーンインストールを行う。
- ① 全シークレットを即ローテーション:npm / GitHub / AWS / SSH / GCP / Azure / Kubernetes / Vault / CircleCI / Docker / GPG /
.env。 - ② 旧版へrevert・当該版をブロック:
package.jsonとlockで侵害前のバージョンに固定する。 - ③ クリーンインストール:
rm -rf node_modules package-lock.json
npm install --ignore-scripts
- ④ 組織レベルのrotation:GitHub Actionsのシークレットはメモリ抽出に備え、組織単位でローテーションする。
- ⑤ ignore-scriptsの既定化:CIの
.npmrcにignore-scripts=trueを追加し、lifecycle scriptの自動実行を止める。
ネイティブモジュール(node-gyp等)はbuildスクリプトが必要な場合がある。許可リスト方式で個別に許可するとよい。
同パターンで狙われやすいパッケージカテゴリ
直近のMini Shai-Hulud系は、共通の「狙いどころ」を持つ。
- 多数の依存元を持つ組織スコープ+自動publishのCIが共通の急所だ。
- 「有名な組織スコープだから安全」という思い込みが、むしろ弱点になる。
頻出する標的カテゴリは次のとおり。
- フロントエンドコンポーネント、APIクライアント、開発ツーリング。
- AI/ML SDK、認証系SDK。
直近の被害例とワームの系譜を整理する。
| 時期 | 事案 | 規模・特徴 |
|---|---|---|
| 2025-09 | Shai-Hulud(初代) | 500+パッケージ。自己増殖ワームの登場 |
| 2025-11 | Shai-Hulud 2.0 | 796パッケージ・週2000万DL。CISAもアラート |
| 2026-05-12 | TanStack | CVE-2026-45321(CVSS 9.6)。OIDC trusted publisher悪用 |
| 2026-05-19 | @antv | 323パッケージを22分で汚染。ソースOSS化で「攻撃の民主化」 |
| 2026-05〜 | Mistral AI / Guardrails AI / SAP系 / Bitwarden | Mini Shai-Hulud亜種が多発 |
| 2026-06-01 | @redhat-cloud-services(Miasma) | 31パッケージ。OIDC+SLSA署名付きで正規publish |
npm/PyPI/crates横断の攻撃カテゴリの広がりはnpm・PyPI・cratesを横断するサプライチェーン攻撃「Trapdoor」も参考になる。
「自分のスタックは無関係」と判断する前に、組織スコープの直接依存とCIのpublish権限を棚卸しすることを勧める。
FAQ
Q. Red Hat製品のユーザーは影響を受けますか?
Red Hat公式は「製品には侵害版が混入・出荷されていない」と表明(バージョンピン留めの徹底による)。ただし当該スコープへ直接依存する自社開発がある場合は要確認です。
Q. Bunが悪いのですか?
いいえ。Bunに脆弱性があるわけではありません。「lifecycle scriptから別ランタイムを呼び出して監視を逃れる手口」が問題で、Bunは悪用された実行環境にすぎません。
Q. SLSA署名は意味がないのですか?
署名は「誰がpublishしたか」を保証するだけです。publish主体自体が乗っ取られれば署名は通ります。「誰が」だけでなく「何を」検証するSCA・ポリシー強制が必要です。
Q. 自分の組織でも起こり得ますか?
npm publish権限のあるCI/GitHubアカウントを持つ全組織が対象です。トークンの短命化・MFA・publish時のhuman approvalが防御の起点になります。
参照ソース
- Wiz Research — Miasma: Supply Chain Attack Targeting RedHat npm Packages
- StepSecurity — Multiple redhat-cloud-services npm Packages compromised
- Aikido — Red Hat npm Packages Compromised to Spread a Credential-Stealing Worm
- RedHatInsights/javascript-clients Issue #492(公式・一次)
- Red Hat Customer Portal — Multiple Supply Chain Attacks against npm Packages(公式)
- Microsoft Security Blog — Shai-Hulud 2.0対策ガイド
- CISA — Widespread Supply Chain Compromise Impacting npm Ecosystem
- Datadog Security Labs — The Shai-Hulud 2.0 npm worm