Aqua Securityが開発するオープンソース脆弱性スキャナ「Trivy」が、2月末から3月22日にかけて多段階のサプライチェーン攻撃を受けました。GitHub Actionsのバージョンタグ汚染、Docker Hubへの侵害イメージ配布、npmエコシステムへのワーム拡散、そしてKubernetesクラスタを破壊するワイパーの投入まで、攻撃は段階的にエスカレートしています。本記事では一次ソースに基づき、攻撃の全容と実務上の点検ポイントを解説します。
インシデントの概要
Trivyはコンテナ、Kubernetes環境、コードリポジトリ、クラウドインフラ全般の脆弱性・設定ミス・シークレット漏洩を検出するスキャナです。GitHub上で広く利用されており、公式GitHub Action(aquasecurity/trivy-action)を参照するワークフローファイルは10,000件以上にのぼります(Socket調べ)。
今回の攻撃は「TeamPCP」と自称する脅威アクターによるもので、単発の侵害ではなく、2月末の初期侵入から3月22日の最新攻撃まで約4週間にわたる連鎖的なキャンペーンです。攻撃者は最初に窃取したクレデンシャルを足がかりに、Trivyのリリースパイプライン、GitHub Actionsタグ、Docker Hubイメージ、さらにnpmエコシステムへと攻撃面を拡大しました。
攻撃タイムライン
2月末:初期侵入
Aqua Securityの公式アドバイザリによれば、2月後半にTrivyのGitHub Actions環境に存在した設定不備が悪用され、特権アクセストークン(PAT)が窃取されました。StepSecurityの分析では、この初期キャンペーンの主体として自律型AIボット「hackerbot-claw」が確認されており、pull_request_targetワークフローの不備を起点にリポジトリの完全な乗っ取りが発生しました。複数のリリースバージョンが削除されたほか、VS Code拡張機能の悪意あるバージョンがOpen VSXに公開されています。
3月1日:第1弾の開示と不完全な封じ込め
Aqua Securityが最初のインシデントを開示し、シークレットとトークンのローテーションを実施しました。しかし、このローテーションはアトミック(全クレデンシャルの同時失効)ではなく、攻撃者がローテーション中に新しいトークンを窃取できる状態でした。Aqua Securityは公式アドバイザリで「最初のインシデントの封じ込めは不完全だった」と認めています。
3月19日:第2弾攻撃(GitHub Actions・バイナリの汚染)
残存クレデンシャルを利用して、攻撃者は以下の操作を実行しました。
trivy-action:77バージョンタグ中76タグをforce-pushで悪性コミットに差し替え(Aqua Security公式アドバイザリより)。正規のTrivyスキャンの前にインフォスティーラーが実行される構成で、スキャン出力は正常に見えるため発見が困難でした。
setup-trivy:全7タグが同様にforce-pushで汚染されました。
Trivyバイナリ v0.69.4:aqua-botサービスアカウント経由でリリースパイプラインが起動され、悪性バイナリがGitHub Releases、Docker Hub、GHCR、ECR Publicの全配布チャネルに公開されました。約3時間後にTrivyチームが検知・封じ込めを行いました。trivy-actionの汚染タグは約12時間にわたり有効でした。
3月20日:npmへの波及(CanisterWorm)
窃取されたnpmパブリッシュトークンを使い、攻撃者は29以上のnpmパッケージに自己増殖型ワーム「CanisterWorm」を注入しました(Socket調べ)。C2にはInternet Computer Protocol(ICP)のキャニスターが使用されており、従来のドメインブロックでは遮断が困難な設計です。
3月22日:Docker Hub侵害イメージ、GitHub org改ざん、Kubernetesワイパー
攻撃はさらに3方向に拡大しました。
Docker Hub:Trivyの0.69.5および0.69.6イメージがGitHubリリースに対応するタグなしでDocker Hubにpushされました。Socketの分析により、バイナリ内にC2ドメインscan.aquasecurtiy[.]org(”security”のタイポスクワット)が確認されています。0.69.3が最後の安全なリリースです。
GitHub org改ざん:Aqua Securityの「aquasec-com」GitHub organizationに属する44の内部リポジトリすべてが、「tpcp-docs-」プレフィックスへのリネームと説明文の書き換えにより改ざんされました。OpenSourceMalwareの分析によれば、20:31:07 UTCから20:32:26 UTCの約2分間にスクリプトで一括実行されており、先のGitHub Actions侵害で窃取された「Argon-DevOps-Mgt」サービスアカウントのトークンが使われたと高い確度で評価されています。このアカウントは2つのGitHub orgにまたがる権限を持つボットアカウントで、1つのトークンで両orgへの書き込み・管理者アクセスが可能だった点が弱点でした。
Kubernetesワイパー:Aikido Securityが発見した新ペイロードについては後述します。
GitHubタグ汚染の手口
今回の攻撃で特徴的なのは、ブランチへのpushや新規リリースの作成ではなく、既存のバージョンタグをforce-pushで差し替えるという手法です。GitHub Actionsのワークフローでaquasecurity/trivy-action@0.33.0のようにバージョンタグで参照している場合、タグが指すコミットSHAが変更されると、ワークフローファイルを一切変えずに悪性コードが実行されます。
攻撃者は各タグについて以下の手順で偽装コミットを作成しました。
まず、masterブランチのHEADツリーをベースにし、entrypoint.shのみをインフォスティーラーに差し替えます。次に、元のタグが指していたコミットのメタデータ(著者名、メールアドレス、タイムスタンプ、PRを含むコミットメッセージ)をそのままコピーします。そして親コミットをmaster HEADに設定し、タグをforce-pushします。
この結果、Socketが詳細に解析した75個の悪性コミットはすべてファイルツリーが同一(master + 差し替えたentrypoint.sh)で、メタデータだけがタグごとに異なるという構造になりました(Aqua公式/GHSAでは76/77タグが汚染と報告されており、分析対象数との差異があります)。
ただし、偽装にはいくつかの検出可能な痕跡があります。元のコミットはGitHub web-flowによるGPG署名が付与されていましたが、攻撃者のコミットは未署名です。またコミット日時が2021年や2022年を主張しているにもかかわらず、親コミットが2026年3月という矛盾があります。さらにGitHubリリースページの「0 commits to master since this release」表示も異常で、2020年のタグであれば数百コミットが表示されるべきですが、親がmaster HEADであるためゼロと表示されます。
GitHubのリリースページには「Immutable」バッジが表示されていましたが、Socketの分析では、攻撃者がタグ汚染時に意図的にImmutableリリースを発行し、メンテナによる復元を困難にした可能性が指摘されています。GitHubの公式セキュリティガイダンスが推奨するとおり、GitHub Actionsの参照は完全なコミットSHAへの固定が唯一の確実な保護策です。
インフォスティーラーの動作
汚染されたentrypoint.shは204行で構成されており、4〜105行目が悪性コード、106〜204行目が正規のTrivyスキャンコードです。悪性コードが先に実行され、その後に正規スキャンが動くため、ユーザーには正常な出力が表示されます。
収集フェーズ:GitHub Actions Runnerのプロセスメモリをダンプし、{"<n>":{"value":"<secret>","isSecret":true}}形式で保持されているシークレットを抽出します。GitHubホステッドランナーではパスワードなしsudoが利用可能なため、/proc/<pid>/memへの直接アクセスが可能です。セルフホステッドランナーでは、SSH鍵、AWS/GCP/Azureクレデンシャル、Kubernetesサービスアカウントトークン、Dockerレジストリ認証、データベースパスワード、暗号資産ウォレットのキーペアなどを網羅的にファイルシステムから走査します。
暗号化フェーズ:収集データをAES-256-CBCで暗号化し、セッション鍵をRSA-4096公開鍵で包みます。攻撃者の秘密鍵がなければ復号できません。
送信フェーズ:暗号化バンドルをscan.aquasecurtiy[.]orgにHTTPS POSTで送信します。送信に失敗した場合のフォールバックとして、被害者のGitHub PATを使い、被害者自身のアカウント上に「tpcp-docs」という公開リポジトリを作成し、リリースアセットとしてデータをアップロードします。攻撃者はGitHub上で「tpcp-docs」リポジトリを検索するだけで窃取データを回収できる設計です。
Kubernetesワイパー:イランを標的とした破壊的ペイロード
Aikido Securityが3月22日に報告した新ペイロードは、TeamPCPのこれまでの活動から一段階エスカレートした内容です。CanisterWormと同じICPキャニスターC2を使用しており、同一キャンペーンの一部と判断されています。
このペイロードは実行環境に応じて4つの経路に分岐します。
Kubernetes環境+イランの場合:「host-provisioner-iran」という名前のDaemonSetをkube-system名前空間にデプロイします。tolerations: [operator: Exists]を指定しているため、コントロールプレーンを含む全ノードにスケジュールされます。コンテナ名は「kamikaze」で、ホストのルートファイルシステムを/mnt/hostにマウントし、トップレベルのファイルをすべて削除した後に強制再起動を実行します。1回のkubectl applyでクラスタ全体が破壊される設計です。
Kubernetes環境+イラン以外の場合:「host-provisioner-std」DaemonSetにより、全ノードにCanisterWormバックドアをsystemdサービスとして永続化します。50分間隔でICPキャニスターをポーリングし、指示されたバイナリをダウンロード・実行します。
非Kubernetes+イランの場合:root権限があればrm -rf / --no-preserve-rootを実行、なければパスワードなしsudoを試みた上で同じコマンドを実行します。
非Kubernetes+イラン以外の場合:何も実行せず終了します。
イランの判定はタイムゾーン(Asia/Tehran、Iran)およびロケール(fa_IR)に基づいています。地理条件を組み込んだ破壊的ペイロードはTeamPCPの活動としては初めて確認されたもので、地政学的動機をうかがわせますが、現時点で動機の断定は避けるべき段階です。
影響規模
StepSecurityが100スター以上の公開リポジトリ767件を対象に実施したスキャンでは、45リポジトリで3月19〜20日の侵害期間中に汚染バージョンのtrivy-actionまたはsetup-trivyを実行したワークフローが確認されました。ただし、この分析はGitHub Actionsでの使用のみを対象としており、Trivyバイナリを直接利用するケースは含まれていません。
Aqua Securityは、現時点で商用製品への影響の兆候はないとしています。商用プラットフォームに組み込まれているTrivyはフォーク版であり、制御された統合プロセスを経てオープンソース版の機能を取り込む設計になっているためです。ただしこの説明はAqua Platform経由の利用に関するもので、オープンソースのTrivyコンポーネントを独自に使用しているユーザーにはそのまま適用されません。
実務者が今すぐ点検したいポイント
CI/CDパイプラインとTrivyバイナリ
aquasecurity/trivy-actionやaquasecurity/setup-trivyをバージョンタグで参照しているワークフローがあれば、完全なコミットSHAへの固定に切り替えてください。3月19〜20日にこれらのアクションを実行したパイプラインがある場合、そのランナー環境でアクセス可能だったすべてのシークレット(クラウドクレデンシャル、SSH鍵、APIトークン、データベースパスワード、npmパブリッシュトークンなど)を侵害済みとして扱い、ローテーションが必要です。
Aqua Security公式アドバイザリでは、GitHub Actionsだけでなく、GitHub Releases、Docker Hub、GHCR、ECR Public、deb/rpmパッケージ、アーティファクトキャッシュなど、あらゆるソースからTrivy v0.69.4バイナリをpullまたは直接実行した環境もすべて点検対象としています。GitHub Actionsを使わずTrivyバイナリを直接CI/CDに組み込んでいるケースも見落とさないよう注意してください。
Docker Hub
Trivyの0.69.4、0.69.5、0.69.6をpullまたは実行していないか確認してください。latestタグも一時期0.69.6を指していました。0.69.3が最後の安全なリリースです。Docker Hubのタグは不変(イミュータブル)ではないため、タグ名だけで整合性を判断すべきではありません。
GitHubアカウントの確認
自組織が管理するGitHub organizationおよびユーザーアカウント配下に「tpcp-docs」という名前のリポジトリが作成されていないか確認してください。フォールバック送信メカニズムは被害者のGitHub PATを使い/user/repos APIで公開リポジトリを作成するため、organization以外のユーザーアカウント上にも作成される可能性があります。このリポジトリの存在は、シークレットが窃取されたことを示す指標です。
Kubernetes環境
kube-system名前空間に自分たちが作成していないDaemonSetがないか確認してください。host-provisioner-iranやhost-provisioner-stdが存在すれば侵害されています。また、hostPath: /を特権コンテキストでマウントするDaemonSetはkubelet等のインフラレベルエージェント以外では使用されるべきではありません。
ホスト側
internal-monitorという名前のsystemdサービス、/var/lib/svc_internal/runner.pyファイル、/tmp/pglogプロセス、icp0[.]ioドメインへのアウトバウンド接続がないか確認してください。
「不完全な封じ込め」が生んだ摩擦
今回のインシデントで見過ごせないのは、最初の侵害(2月末)に対するクレデンシャルローテーションが「アトミックでなかった」ことが、3月19日以降の全攻撃の起点になった点です。Aqua Securityは「シークレットとトークンのローテーションを実施したが、プロセスがアトミックではなく、攻撃者がリフレッシュされたトークンを入手できた可能性がある」と説明しています。
OpenSourceMalwareの分析が指摘するとおり、「Argon-DevOps-Mgt」という1つのボットアカウントが2つのGitHub organizationをまたいで書き込み・管理者権限を持っていた構造も、被害拡大の要因です。侵害されたトークンが1つであっても、そのトークンの権限範囲が広ければ被害は連鎖します。
セキュリティベンダー自身がクラウドネイティブの脅威アクターに侵害されたという皮肉は、どの組織にとっても無関係ではありません。CI/CDパイプラインにおけるGitHub Actionsのタグ固定、サービスアカウントの最小権限設計、インシデント封じ込め時のクレデンシャルローテーションの原子性は、今すぐ自組織で検証すべき項目です。
IoC(侵害指標)一覧
ネットワーク
| 種別 | 値 | 用途 |
|---|---|---|
| ドメイン | scan.aquasecurtiy[.]org | 主要C2(タイポスクワット) |
| IP | 45.148.10[.]212 | C2解決先 |
| ICP canister | tdtqy-oyaaa-aaaae-af2dq-cai[.]raw[.]icp0[.]io | CanisterWorm C2(デッドドロップ) |
| Cloudflareトンネル | souls-entire-defined-routes[.]trycloudflare[.]com | ワイパーペイロード配信(初期) |
| Cloudflareトンネル | investigation-launches-hearings-copying[.]trycloudflare[.]com | ワイパーペイロード配信(後期) |
侵害されたアーティファクト
| 対象 | 詳細 |
|---|---|
| Trivyバイナリ | v0.69.4(全配布チャネル) |
| Docker Hubイメージ | aquasec/trivy:0.69.4、0.69.5、0.69.6(latestも一時汚染) |
| trivy-action | 76/77タグ(0.35.0のみ安全) |
| setup-trivy | 全7タグ |
ファイル・プロセス(ホスト)
| 指標 | 備考 |
|---|---|
| /var/lib/svc_internal/runner.py | CanisterWormバックドア |
| /etc/systemd/system/internal-monitor.service | 永続化サービス |
| /tmp/pglog | 実行時プロセス |
| /tmp/.pg_state | 状態ファイル |
| entrypoint.sh SHA256 | 18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a |
Kubernetes
| 指標 | 備考 |
|---|---|
| DaemonSet: host-provisioner-iran | kube-system名前空間、ワイパー |
| DaemonSet: host-provisioner-std | kube-system名前空間、バックドア |
| コンテナ名: kamikaze | ワイパー用 |
| コンテナ名: provisioner | バックドア設置用 |
GitHub
| 指標 | 備考 |
|---|---|
| tpcp-docsリポジトリ | フォールバック送信先(被害者アカウント上に作成) |
一次ソース:
Aqua Security公式アドバイザリ(2026年3月23日更新) ── aquasec.com
GitHub Security Advisory GHSA-69fq-xp46-6×23 ── github.com
Socket Security「Trivy Docker Images Compromised」(2026年3月22日) ── socket.dev
Socket Security「Trivy Under Attack Again: GitHub Actions Tag Compromise」(2026年3月20日) ── socket.dev
Aikido Security「CanisterWorm Gets Teeth: TeamPCP’s Kubernetes Wiper」(2026年3月22日) ── aikido.dev
OpenSourceMalware「TeamPCP aquasec-com GitHub Org Compromise」(2026年3月22日) ── opensourcemalware.com
Wiz Research「Trivy Compromised by TeamPCP」(2026年3月19日、3月22日更新) ── wiz.io
StepSecurity「Trivy Compromised a Second Time」(2026年3月23日更新) ── stepsecurity.io

コメント