注:GitLab製品は、本記事で言及されている侵害されたパッケージバージョンを使用していませんでした。
わずか12日間で4件の独立したサプライチェーン攻撃が発生し、継続的インテグレーション/継続的デリバリー(CI/CD)パイプラインが高度な脅威アクターにとって格好の標的となっていることが明らかになりました。
2026年3月19日から31日にかけて、脅威アクターは以下のツールを侵害しました。
- オープンソースのセキュリティスキャナー(Trivy)
- Infrastructure as Code(IaC)セキュリティスキャナー(Checkmarx KICS)
- AIモデルゲートウェイ(LiteLLM)
- JavaScript HTTPクライアント(axios)
いずれの攻撃も同じ侵入口を狙っていました。それがビルドパイプラインです。 本記事では、何が起きたのか、なぜパイプラインが特に脆弱なのか、そしてGitLabの集中型ポリシー適用(以下で定義するポリシーを使用)が、これらの攻撃パターンを本番環境に到達する前にブロック・検出・封じ込める方法を解説します。
数百万人が信頼するツールが、わずか数分で侵害された
サプライチェーン攻撃のタイムラインは以下のとおりです。
3月19日:Trivyセキュリティスキャナーが攻撃のベクターに
Trivyは、世界で最も広く使われているオープンソースの脆弱性スキャナーの1つです。脆弱性を検出するためにパイプライン内で実行されるツールです。
3月19日、TeamPCPと呼ばれる脅威アクターグループが侵害された認証情報を使用し、aquasecurity/trivy-action GitHub Actionの76バージョンタグ(全77件中)およびaquasecurity/setup-trivyの全7タグに悪意のあるコードをforce-pushしました。同時に、トロイの木馬化されたTrivyバイナリ(v0.69.4)が公式配布チャネルに公開されました。このペイロードは認証情報を窃取するマルウェアで、Trivyスキャンを実行したすべてのパイプラインから環境変数、クラウドトークン、SSHキー、CI/CDシークレットを収集しました。
このインシデントにはCVE-2026-33634が割り当てられ、CVSSスコアは9.4でした。米国サイバーセキュリティ・インフラストラクチャセキュリティ庁(CISA)は数日以内にこれを既知の悪用済み脆弱性カタログに追加しました。
3月23日:次はCheckmarx KICSが標的に
TeamPCPは窃取した認証情報を使い、CheckmarxのオープンソースプロジェクトであるKICS(Keeping Infrastructure as Code Secure)に攻撃対象を移しました。ast-github-actionおよびkics-github-action GitHub Actionに同じ認証情報窃取マルウェアを注入し、3月23日の12:58〜16:50 UTCの間、これらのアクションを参照するCI/CDパイプラインはすべて、APIキー、データベースパスワード、クラウドアクセストークン、SSHキー、サービスアカウントの認証情報などの機密データを密かに外部に送信していました。
3月24日:Trivyの侵害された認証情報を経由してLiteLLMも被害を受ける
月間9,500万ダウンロードのLLM APIプロキシであるLiteLLMが次の標的になりました。TeamPCPは、TrivyでスキャンしていたLiteLLM自身のCI/CDパイプラインから収集した認証情報を使用し、PyPIにバックドアを仕込んだバージョン(1.82.7および1.82.8)を公開しました。
バージョン1.82.7を標的としたマルウェアは、litellm/proxy/proxy_server.pyにインポート時に実行されるbase64エンコードされたペイロードを直接注入していました。バージョン1.82.8を標的としたものは、Pythonインタープリタ起動時に自動実行される.pthファイルを使用していました。LiteLLMをインストールするだけでペイロードが起動してしまう仕組みです。攻撃者は窃取したデータ(SSHキー、クラウドトークン、.envファイル、暗号資産ウォレット)を暗号化し、本物のドメインに似せたmodels.litellm.cloudに外部送信しました。
3月31日:単純なパッケージングミスがAIコーディングアシスタントのソースコードを流出させる
TeamPCPの攻撃キャンペーンがまだ続く中、あるソフトウェア企業が59.8 MBのソースマップファイルを含むnpmパッケージを公開してしまいました。そのファイルには、AIコーディングアシスタントの完全な未縮小TypeScriptソースコードへの参照が含まれており、自社のCloudflare R2バケットでホストされていました。
この流出により、1,900のTypeScriptファイル、512,000行以上のコード、44の隠し機能フラグ、未公開のモデルコードネーム、そして知る人ぞ知る場所へのアクセス方法を知っていれば誰でも確認できるシステムプロンプトの全文が公開されてしまいました。エンジニアのGabriel Anhaia氏が解説したように、「.npmignoreまたはpackage.jsonのfilesフィールドの設定ミスが1つあるだけで、すべてが露出してしまいます」。
3月31日:axiosとサプライチェーンへのもう1つのトロイの木馬
同日、週間1億ダウンロード超のJavaScript HTTPクライアントであるaxios npmパッケージを狙った高度なキャンペーンが実行されました。
侵害されたメンテナーアカウントによりバックドアを仕込んだバージョン(1.14.1および0.30.4)が公開されました。悪意のある依存関係([email protected])が注入され、macOS、Windows、Linuxで動作するリモートアクセス型トロイの木馬(RAT)がデプロイされました。2つのリリースブランチともに39分以内に感染し、マルウェアは実行後に自己消去するよう設計されていました。
これらの攻撃に潜む共通パターン
5件のインシデントを通じて、3つの明確な攻撃パターンが浮かび上がってきます。いずれもCI/CDパイプラインがその入力に対して暗黙的に持つ信頼を悪用するものです。
パターン1:汚染されたツールとアクション
TeamPCPのキャンペーンは、ある根本的な前提を突いていました。それは、パイプライン内で実行されるセキュリティツール自体は信頼できるという思い込みです。GitHubアクションのタグやPyPIパッケージのバージョンが悪意のあるコードに解決された場合、パイプラインはそれを環境シークレット、クラウド認証情報、デプロイトークンへのフルアクセス権限で実行してしまいます。パイプラインはタグを信頼するため、検証ステップが存在しないのです。
推奨されるパイプラインレベルの対策: 可変バージョンタグではなく、不変の参照(コミットSHAまたはイメージダイジェスト)にツールとアクションをピン留めしてください。ピン留めが現実的でない場合は、既知の正常なチェックサムまたは署名に対してツールと依存関係の整合性を検証してください。検証に失敗した場合は実行をブロックします。
パターン2:知的財産(IP)を漏洩するパッケージング設定ミス
設定ミスのあるビルドパイプラインが、デバッグ成果物をそのまま本番パッケージに含めて出荷してしまいました。.npmignoreまたはpackage.jsonのfilesフィールドの設定ミスが1つあれば十分です。公開前の検証ステップを設けておけば、こうした問題は毎回防ぐことができます。
推奨されるパイプラインレベルの対策: パッケージを公開する前に、パッケージの内容を許可リストに対して検証し、予期しないファイル(ソースマップ、内部設定ファイル、.envファイル)をフラグとして検出し、チェックに失敗した場合は公開ステップをブロックする自動チェックを実行してください。
パターン3:推移的依存関係の脆弱性
axiosへの攻撃は、axiosを直接使用しているユーザーだけでなく、依存関係ツリーが侵害されたバージョンに解決されるすべてのユーザーを標的にしました。ロックファイル内で一度依存関係が汚染されると、組織全体のビルドインフラに波及する可能性があります。
推奨されるパイプラインレベルの対策: 依存関係のチェックサムを既知の正常なロックファイルの状態と比較してください。予期しない新しい依存関係やバージョン変更を検出し、未検証のパッケージを導入するビルドをブロックします。
GitLabパイプライン実行ポリシーによる各攻撃パターンへの対処
GitLabパイプライン実行ポリシー(PEP)は、セキュリティチームおよびプラットフォームチームが、開発者が.gitlab-ci.ymlで定義した内容に関わらず、組織全体のすべてのパイプラインに必須のCI/CDジョブを注入できる仕組みです。PEPで定義されたジョブは、[skip ci]や[no_pipeline]ディレクティブを使ってもスキップできません。ジョブは開発者のパイプラインを前後から挟む予約済みステージ(.pipeline-policy-preおよび.pipeline-policy-post)で実行できます。
3つのパターンすべてに対応するパイプライン実行ポリシーをオープンソースプロジェクトとして公開しています:Supply Chain Policies。これらのポリシーは独立してデプロイ可能で、それぞれテスト用の違反サンプルが同梱されています。各ポリシーの仕組みをご紹介します。
ユースケース1:パッケージ公開時の意図しない情報露出を防ぐ
問題: ビルドパイプラインが公開時の検証をスキップしたため、ソースマップファイルがAIコーディングツールのnpmパッケージに含まれてしまいました。
PEPによるアプローチ: この種のエラーに特化したオープンソースのパイプライン実行ポリシーを作成しました:Artifact Hygiene。
このポリシーは、公開ステップが実行される前に、アーティファクトタイプ(npmパッケージ、Dockerイメージ、またはHelmチャート)を自動検出してその内容を検査する.pipeline-policy-preジョブを注入します。npmパッケージに対しては、3つのチェックを実行します。
- ファイルパターンのブロックリスト。 npm packの出力をスキャンし、ソースマップ(.map)、テストディレクトリ、ビルド設定、IDE設定、src/ディレクトリを検出します。
- パッケージサイズゲート。 AIツールを流出させた59.8 MBパッケージのように、50 MBを超えるパッケージをブロックします。
- sourceMappingURLスキャン。 外部URL(大手AI企業のソースコードを露出させたR2バケットのパターン)、インラインのdata: URI、JavaScriptバンドルに埋め込まれたローカルファイル参照を検出します。
違反が検出されると、パイプラインは失敗したCIジョブのログに明確なレポートを出力して終了します。
=============================================
FAILED: 3 violation(s) found
=============================================
BLOCKED: dist/index.js.map (matched: \.map$)
BLOCKED: dist/index.js contains external sourceMappingURL
BLOCKED: dist/utils.js contains inline sourceMappingURL
This check is enforced by a Pipeline Execution Policy. If this is a false positive, contact the security team to update the policy project or exclude this project.
このポリシーには、ユーザーが設定できるCI変数はありません。開発者が無効化したり回避したりすることはできません。例外はポリシーレベルでセキュリティチームが管理するため、意図的なプロセスと明確な監査証跡が確保されます。
リポジトリには意図的な違反を含むテストプロジェクト(examples/leaky-npm-package/)が含まれており、組織にデプロイする前にポリシーの動作を確認できます。READMEには、セットアップとデプロイの完全なクイックスタートガイドが含まれています。
検出できる問題: これらのコントロールのどれか1つでもあれば、AI企業のソースコード流出は防げていた可能性があります。
- ソースマップファイルはファイルパターンのブロックリストに引っかかります。
- 59.8 MBというサイズはサイズゲートに引っかかります。
- 外部R2バケットを指すsourceMappingURLはURLスキャンに引っかかります。
ユースケース2:依存関係の改ざんとロックファイル操作を検出する
問題: axiosへの攻撃では、インストール時にRATを実行する悪意のある推移的依存関係(plain-crypto-js)が導入されました。侵害が行われた期間中にnpm installを実行したすべての人がトロイの木馬を取り込んでしまいました。
PEPによるアプローチ: Dependency Integrityポリシーは、パッケージエコシステム(npmまたはPython)を自動検出し、3つのチェックを実行する.pipeline-policy-preジョブを注入します。
npmプロジェクトの場合(package-lock.json、yarn.lock、またはpnpm-lock.yamlによってトリガー):
- ロックファイルの整合性。
npm ci --ignore-scriptsを実行します。node_modulesの内容がロックファイルの指定と異なる場合、失敗します。これにより、package.jsonは更新されたがロックファイルが再生成されていないケースを検出し、SRIインテグリティハッシュも検証します。 - ブロックパッケージスキャン。 ロックファイルの完全な依存関係ツリーを、侵害が確認済みのパッケージバージョンのGitLab管理リストである
blocked-packages.ymlと照合します。同梱のブロックリストには[email protected]、[email protected]、[email protected]が含まれています。 - 未宣言の依存関係の検出。 インストール後、node_modulesの内容をロックファイルと比較します。ディスク上に存在するがロックファイルに存在しないパッケージは改ざんの証拠です(例:追加パッケージを取得する侵害されたpostinstallスクリプト)。
Pythonプロジェクトの場合(requirements.txt、Pipfile.lock、poetry.lock、またはuv.lockによってトリガー):
- ロックファイルの整合性。 分離された仮想環境にインストールし、ロックファイルからのインストールが成功することを確認します。
- ブロックパッケージスキャン。 同じブロックリストのアプローチです。同梱リストには
litellm==1.82.7およびlitellm==1.82.8が含まれています。 - .pthファイルの検出。 site-packagesの
.pthファイルをスキャンし、実行可能なコードパターン(import os、exec(、eval(、__import__、subprocess、socket)を検出します。これはLiteLLMバックドアが使用したまさにその仕組みです。
違反が検出されると:
=============================================
FAILED: 1 violation(s) found
=============================================
BLOCKED: [email protected] is a known-compromised package
This check is enforced by a Pipeline Execution Policy.
このポリシーはストリクトモードで動作します。コミット済みのロックファイルに存在しない依存関係は、パイプラインをブロックします。開発者が依存関係を追加する必要がある場合は、更新されたロックファイルをコミットします。ポリシーはインストールされたバージョンがコミットされたバージョンと一致することを確認します。コミットされていないものが現れた場合(例:侵害されたアップストリームパッケージ経由で注入された推移的依存関係)、パイプラインはブロックされます。
検出できる問題: plain-crypto-jsという新規かつ未確認の依存関係の導入は、未宣言の依存関係チェックによってフラグが立てられます。[email protected]バージョンはブロックパッケージスキャンによって検出されます。LiteLLMの.pthファイルは.pth検出チェックによって検出されます。各攻撃に対して、少なくとも1つ、多くの場合は2つの独立した検出シグナルがあります。
ユースケース3:侵害されたツールを実行前に検出・ブロックする
問題: TeamPCPは、信頼できるTrivyとCheckmarxのGitHubアクションタグを悪意のあるバージョンに置き換えました。これらのタグを参照するパイプラインはすべて、認証情報を窃取するマルウェアを実行してしまいました。
PEPによるアプローチ: Tool Integrityポリシーは、GitLab CI Lint API(またはフォールバックとして.gitlab-ci.ymlを評価する仕組み)にクエリを発行し、コンテナイメージの参照を抽出して、セキュリティチームが管理する承認済みイメージ許可リストと照合する.pipeline-policy-preジョブを注入します。
許可リスト(approved-images.yml)は、イメージごとに3つの制御をサポートしています。
承認済みリポジトリ: リスト上のリポジトリからのイメージのみが許可されます。未知のリポジトリはパイプラインをブロックします。
許可されているタグ: 承認済みリポジトリ内でも、特定のタグのみが許可されます。これにより、未テストバージョンへの移行を防ぎます。
ブロックされているタグ: リポジトリが承認済みであっても、既知の侵害バージョンを明示的にブロックできます。同梱の許可リストは、TeamPCPがトロイの木馬化した正確なバージョンであるaquasec/trivy:0.69.4から0.69.6をブロックします。
違反が検出されると、他のジョブが実行される前にパイプラインが失敗します。
=============================================
FAILED: 1 violation(s) found
=============================================
BLOCKED: aquasec/trivy:0.69.4 (job: trivy-scan)
- tag '0.69.4' is known-compromised
This check is enforced by a Pipeline Execution Policy.
許可リストは、ポリシープロジェクトに対するMRを通じて管理されます。新しい承認済みイメージを追加するには、セキュリティチームがMRを開きます。新たな侵害への対応には、ブロックするタグを追加するだけです。コードの変更は不要で、YAMLだけで管理できます。
検出できる問題: 未承認のタグを持つイメージが検出されると、ポリシーはイメージのリポジトリ名とタグを許可リストと照合します。一致しない場合、スキャナーが実行される前にパイプラインをブロックし、認証情報の外部送信を防ぎます。
注:上記のサンプルを拡張することで、PEPをタグではなくダイジェストへのピン留めを強制するために使用できます。これはforce pushに対して耐性があります。このサンプルは、より基本的なタグベースの適用パターンを示しています。
PEPを超えて:GitLabのサプライチェーン防御
パイプライン実行ポリシーは適用のレイヤーですが、サプライチェーン保護において多層防御(defense-in-depth)戦略の一部として機能するときに最大の効果を発揮します。GitLabは、サプライチェーン保護においてPEPを補完するいくつかの機能を提供しています。
シークレット検出
GitLabのシークレット検出は、認証情報がそもそもリポジトリに入り込むことを防ぎ、侵害されたパイプラインツールが収集できる情報を大幅に削減します。2026年3月の攻撃の文脈では:
- リポジトリに保存された認証情報は、攻撃者にとって発見しやすく、ローテーションも遅くなります。Trivyのインシデントでは、ローテーションプロセス自体も悪用されました。Aqua Securityのローテーションはアトミックではなく、攻撃者は古いトークンが完全に失効する前に新たに発行されたトークンを取得しました。GitLabのシークレット検出には、漏洩したGitLabトークンの自動失効機能と、サードパーティプロバイダーへの認証情報失効通知を行うパートナーAPIが含まれており、侵害発生時の対応を迅速化します。
- シークレット検出と適切なシークレット管理(短命トークン、Vault基盤の認証情報、パイプラインシークレットへの最小限の露出)を組み合わせることで、信頼済みツールが悪意を持つ動作をした場合でも、攻撃者がアクセスできる範囲を制限します。
ソフトウェアコンポジション解析(SCA)による依存関係スキャン
GitLabの依存関係スキャンは、ロックファイルとマニフェストを解析することで、プロジェクトの依存関係における既知の脆弱性を特定します。2026年3月の攻撃の文脈では:
- LiteLLMについては、侵害されたバージョン(1.82.7、1.82.8)がGitLabのアドバイザリデータベースで追跡されており、影響を受けるPythonプロジェクトに自動的にフラグを立てます。
- axiosについては、依存関係スキャンが組織内のすべてのプロジェクトで侵害されたバージョン(1.14.1、0.30.4)を特定し、セキュリティチームに影響範囲の評価と認証情報ローテーションの優先順位付けのための一元的なビューを提供します。
- 同様に、TeamPCPのCanisterWorm伝播によって侵害されたすべてのnpmパッケージも、使用されている場合はフラグが立てられます。
GitLabコンテナスキャンは、デプロイメントで使用される脆弱なコンテナイメージを検出します。Trivyの侵害については、コンテナスキャンがコンテナレジストリまたはデプロイメントマニフェストに現れたトロイの木馬化されたTrivyのDockerイメージ(0.69.4〜0.69.6)にフラグを立てます。
マージリクエスト承認ポリシー
マージリクエスト承認ポリシーは、依存関係のロックファイルやCI/CD設定への変更がマージされる前にセキュリティチームの承認を必須とすることができます。これにより、サプライチェーン攻撃が一般的に導入する種類の変更に対して、人間によるチェックポイントが確保されます。
近日公開予定:依存関係ファイアウォール、アーティファクトレジストリ、SLSAレベル3の認証と検証
今後予定されているGitLabのサプライチェーンセキュリティ機能は、レジストリとパイプラインという2つの重要なコントロールポイントにおけるポリシー適用を強化します。依存関係ファイアウォールとアーティファクトレジストリは非準拠のパッケージをブロックし、SLSAレベル3の認証によってアーティファクトが承認されたパイプラインで生成され、改ざんされていないという暗号学的な証明が提供されます。これらを組み合わせることで、セキュリティチームはソフトウェアサプライチェーンへの入出力を検証可能な形で管理できるようになります。
あなたの組織にとっての意味
AI支援型の脅威が高まる中、CI/CDパイプラインへの攻撃はますます一般的になっています。TeamPCPのキャンペーンは、1つの侵害された認証情報が信頼済みツールのエコシステム全体にどう波及するかを示しています。
影響を受けたコンポーネントを使用していた場合は、すべてのパイプラインシークレットが露出したという前提で行動してください。直ちにローテーションし、永続的なバックドアがないかシステムを監査してください。いずれの場合も、認証情報を定期的にローテーションし、短命トークンを使用することで、将来の侵害のブラスト半径を制限できます。
推奨事項をまとめます:
- 可能な限り、依存関係をチェックサムにピン留めしてください。 TeamPCPが悪用した可変バージョンタグは、セキュリティ境界ではありません。すべてのCI/CDコンポーネント、アクション、コンテナイメージにはSHAピン留め参照を使用してください。
- 実行前の整合性チェックを実行してください。 パイプライン実行ポリシーを使用して、パイプラインジョブが実行される前にツールと依存関係の整合性を確認してください。これが
.pipeline-policy-preステージです。 - 公開するものを監査してください。 すべてのパッケージ公開ステップには、アーティファクトの内容を自動検証する処理を含めてください。ソースマップ、環境ファイル、内部設定はビルド環境から外部に出すべきではありません。Supply Chain Policyプロジェクトは、npm、Docker、Helmアーティファクトのすぐにデプロイできる出発点を提供しています。
- 依存関係のドリフトを検出してください。 すべてのパイプライン実行において、依存関係の解決結果をコミット済みロックファイルと比較してください。予期しない新しい依存関係を監視します。
- ポリシー管理を集中化してください。 セキュリティチェックを含めることを開発者の記憶に頼らないでください。開発者が削除やスキップをできないポリシーを通じて、グループまたはインスタンスレベルで適用してください。
- セキュリティツール自体が標的になると想定してください。 脆弱性スキャナー、静的アプリケーションセキュリティテスト(SAST)ツール、AIゲートウェイは侵害される可能性があります。各ツールの権限は最低限必要なものに限定し、その他へのアクセスが不可能であることを確認してください。
GitLabでパイプラインを保護する
2週間にわたり、攻撃者はソフトウェア開発エコシステムで最も広く採用されているツールの一部を使用している組織の本番パイプラインを侵害しました。
教訓は明確です。ビルドパイプラインには、ネットワークやクラウドインフラに適用するのと同じレベルの集中管理されたポリシー駆動の保護が必要です。
GitLabパイプライン実行ポリシーは、その適用レイヤーを提供します。個々のプロジェクト設定に関わらず、すべてのプロジェクトのすべてのパイプラインでセキュリティチェックが実行されることを保証します。依存関係スキャン、シークレット検出、マージリクエスト承認ポリシーと組み合わせることで、2026年3月に見られたクラスの攻撃をブロック、検出、封じ込めることができます。
Supply Chain Policiesプロジェクトは、大手AI企業の流出事故の背後にある種類のエラーを正確に検出する、動作するパイプライン実行ポリシーを提供しています。npmパッケージ、Dockerイメージ、Helmチャートに対応しています。クローンして、グループにデプロイし、今後のサプライチェーン攻撃に備えてすべてのパイプラインを準備してください。
集中管理されたパイプラインポリシーを始めるには、GitLab Ultimateの無料トライアルにサインアップしてください。
このブログ記事には、1933年証券法第27A条(改正済み)および1934年証券取引法第21E条の意味における「将来の見通しに関する記述」が含まれています。これらの記述に反映された予想は合理的であると信じておりますが、実際の結果や成果を大幅に異なるものにする可能性のある既知および未知のリスク、不確実性、前提条件、その他の要素の影響を受けることがあります。これらのリスクおよびその他の要素に関するさらなる情報は、SECへの提出書類の「リスク要因」という見出しの下に記載されています。法律で要求される場合を除き、このブログ投稿の日付以降にこれらの記述を更新または修正する義務を負いません。


