12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

2026年3月に相次いだOSSサプライチェーンインシデントから学ぶ防御策

12
Posted at

はじめに

2026年3月、OSSサプライチェーンを狙ったインシデントが集中的に発生しました。脆弱性スキャナ自体が侵害される、npmパッケージに悪意あるコードが仕込まれる、AIエージェントのスキル定義が乗っ取り可能だと判明する。いずれも開発者のCI/CDパイプラインや依存関係を経由した攻撃です。

本記事では各インシデントの概要を整理し、開発者が今すぐ実施できる防御策に焦点を当てます。

なぜ今、依存関係のセキュリティが重要なのか

ソフトウェアサプライチェーン攻撃は増加の一途をたどっています。ReversingLabsの2026年レポートでは、ソフトウェアサプライチェーンへの脅威が前年比73%増加したと報告されています。

背景には、開発環境の変化があります。

  • AIエージェントが依存パッケージを自動インストールする時代になった: npm installpip installをAIが自律的に実行するワークフローが一般化しつつあります。人間がパッケージ名を目視確認する機会が減り、タイポスクワッティングの成功率が上がっています
  • CI/CDパイプラインは昇格された権限で動作する: クラウドの認証情報、デプロイキー、パッケージ公開トークンなど、本番環境に直結するシークレットがCI/CD上に集中しています
  • サプライチェーンの監視範囲が追いついていない: 多くの企業が拡張ソフトウェアサプライチェーンの全体を監視できていないのが現状です

Sonatypeの集計では、Maven Central、PyPI、npm、NuGetにわたって1年間に45万件以上の悪意あるパッケージが公開されました。攻撃は「珍しい出来事」ではなく、日常的に発生しています。

インシデント概要

Trivy GitHub Actions タグ侵害(3月19日)

脆弱性スキャナTrivyを開発するAqua Securityに対し、GitHubの組織アカウントが侵害されました。攻撃者(TeamPCP)はaquasecurity/trivy-actionリポジトリの77タグ中76タグをforce-pushで書き換え、悪意あるコードを注入しました。さらにaquasecurity/setup-trivyの全7タグも同様に差し替えられています。

このActionをCI/CDパイプラインで使用していた場合、ワークフロー実行時にSSHキー、クラウド認証情報、Dockerの設定、Kubernetesトークンなどがビルドログ経由で外部に漏洩するリスクがありました。悪意あるリリース(v0.69.4)は約3時間、侵害されたActionsタグは最大12時間にわたって公開されていました。

Trivy Actionをタグ指定(例: @v1)で利用していた場合、タグの指す先が攻撃者のコードに差し替えられていた可能性があります。該当するワークフローのシークレットをローテーションしてください。

根本原因は、2026年2月下旬にGitHub Actionsの設定不備から特権アクセストークンが流出したことです。3月1日に認証情報のローテーションが行われましたが、一部の認証情報が残存しており、3月19日の本格的な侵害につながりました。

なお、3月22日にはv0.69.5およびv0.69.6がDocker Hub上で公開されましたが、これらのイメージも侵害の影響を受けている可能性が指摘されています。Trivyを利用している場合は、Docker Hubのイメージについても公式のセキュリティアドバイザリを確認してください。

悪意あるnpmパッケージによるタイポスクワッティング攻撃

2026年3月には、正規のKubernetes関連パッケージに酷似した名前の悪意あるnpmパッケージが複数確認されています。これらのパッケージは、インストール時のpostinstallスクリプトでリバースシェルを確立し、攻撃者にシステムへのアクセスを提供する仕組みでした。

対象となったパッケージは、Kubernetesのデプロイツールやヘルムチャート関連のユーティリティに見せかけたものです。名前の類似性を利用したタイポスクワッティング(入力ミスを狙った名前の偽パッケージ)の手法が使われていました。

npmパッケージをインストールする際は、パッケージ名のスペルを正確に確認してください。特にAIエージェントにパッケージインストールを任せている場合、エージェントが類似名のパッケージを選択するリスクがあります。公式ドキュメントに記載されたパッケージ名と一致するかを検証する仕組みを設けてください。

AIエージェントスキルのリポジトリジャッキング脆弱性(研究・脅威動向)

セキュリティ研究者らが、AIエージェントフレームワークのスキル定義を調査した結果、7つのリポジトリにまたがる121のスキルが、GitHubユーザー名のハイジャック(リポジトリジャッキング)に対して脆弱であることが判明しました。

この攻撃は、スキル定義で参照されているGitHubリポジトリの所有者がアカウント名を変更した場合に成立します。攻撃者が旧ユーザー名を取得し、同名のリポジトリを作成すれば、エージェントは攻撃者のコードを正規のスキルとして読み込んでしまいます。

より大きな問題として、OpenClawのスキルレジストリ(ClawHub)では1,184件の悪意あるスキルが確認されています。全体の約12%が侵害されていた計算になります。さらに、BlueRock Securityの調査では7,000以上のMCPサーバーの36.7%にSSRF脆弱性が存在し、セキュリティ研究者が30,000以上のスキルを分析した結果、4分の1以上に脆弱性が含まれていたことが報告されています。

AIエージェントにサードパーティのスキルやプラグインを導入する際は、参照先リポジトリの所有者が実在し、アクティブであることを確認してください。フォークやミラーではなく、公式リポジトリを直接参照しているかの検証も必要です。

セキュリティベンダー自身の組織侵害

上記Trivyの件と関連して、Aqua Security自体のGitHub組織アカウントが侵害されたことは、セキュリティベンダーであっても攻撃対象になりうることを示しています。公式の発表では、侵害の起点は「compromised credentials」(侵害された認証情報)とされており、特権トークンが悪用されたと報告されています。

この事実は、「セキュリティツールだから安全」という前提が成り立たないことを意味します。利用するツールの提供元に関わらず、自組織側での検証と防御が不可欠です。

サプライチェーン攻撃の進化: レジストリからAIエージェントへ

これらのインシデントは、サプライチェーン攻撃の対象領域が段階的に拡大してきた流れの中に位置づけられます。

第1世代: パッケージレジストリ(2018年頃〜)

npmやPyPIに悪意あるパッケージを公開し、開発者のインストールを待つ手法です。タイポスクワッティングや依存性混乱(dependency confusion)が代表的な攻撃パターンです。npmだけでも悪意あるパッケージの報告件数は2018年の38件から2024年には2,000件超へと増加しました。

第2世代: CI/CDパイプライン(2020年頃〜)

SolarWindsインシデント(2020年)を契機に注目された、ビルドパイプラインへの介入です。GitHub Actionsのタグ書き換え、ビルドスクリプトの改ざん、CI/CD環境からのシークレット窃取がこの世代に該当します。今回のTrivyインシデントもこの世代に分類されます。

第3世代: AIエージェントスキル(2025年〜)

AIエージェントのプラグインやスキル定義を狙う攻撃です。スキルスクワッティング、リポジトリジャッキング、プロンプトインジェクションを組み合わせた手法が確認されています。従来のパッケージ攻撃と異なり、スキルの説明文自体がLLMのプロンプトに注入されるため、攻撃の影響範囲が広くなる特徴があります。

共通するのは、開発者が暗黙的に信頼しているコンポーネントを狙っている点です。

攻撃経路 信頼の前提 今回の事例
パッケージレジストリ 名前が正しければ正規パッケージ TeamPCPのタイポスクワッティング
GitHub Actions タグが同じなら同じコード Trivyタグ書き換え
エージェントスキル リポジトリURLが有効なら安全 ユーザー名ハイジャック

開発者が今すぐ実施すべき防御策

1. GitHub Actionsのピン留め(タグではなくSHAで指定)

GitHub Actionsをタグ(@v1@latestなど)で参照していると、タグの指す先が変更された場合に悪意あるコードを実行してしまいます。コミットSHAで固定することで、このリスクを大幅に低減できます。ただし、ピン留めしたコミットが内部で参照する依存関係(サブモジュールや外部イメージなど)がmutableな場合は完全な防御にはなりません。内部依存や再帰的な参照も含めて確認することが重要です。

# 危険: タグ指定(書き換え可能)
- uses: aquasecurity/trivy-action@v1

# 安全: コミットSHA指定(不変)
- uses: aquasecurity/trivy-action@a7b7e35c6e8e1a0c4e89b0e4b2f5a2e8d1c3b5a7

SHAピン留めの手順

手順1: 使用中のActionのバージョンを特定する

まず、ワークフローファイルでタグ指定になっているActionを洗い出します。

# リポジトリ内のワークフローファイルから、SHA指定でないActionを検索
grep -rn 'uses:' .github/workflows/ | grep -v '@[a-f0-9]\{40\}' | grep '@'

手順2: タグに対応するコミットSHAを取得する

# 方法1: git ls-remoteで確認
git ls-remote https://github.com/actions/checkout.git refs/tags/v4

# 方法2: GitHub CLIで確認(タグの詳細情報を取得)
gh api repos/actions/checkout/git/ref/tags/v4 --jq '.object.sha'

# 注意: annotated tagの場合はtagオブジェクトのSHAが返される
# その場合はさらにコミットSHAを取得する
gh api repos/actions/checkout/git/tags/<tag-sha> --jq '.object.sha'

手順3: ワークフローファイルを更新する

# 変更前
- uses: actions/checkout@v4
- uses: actions/setup-node@v4

# 変更後(SHAはインラインコメントでバージョンを記録)
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4

SHAの横に# v4のようなコメントを残しておくと、どのバージョンをピン留めしているか一目でわかります。Dependabotもこのコメントを認識し、更新PRに反映してくれます。

手順4: Dependabotで自動更新を設定する

SHA指定にすると手動での更新が面倒になりますが、Dependabotを設定すれば更新PRを自動生成してくれます。

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

手順5: 既存のワークフローを一括変換する(オプション)

StepSecurityが提供するsecure-repoツールを使うと、リポジトリ内の全ワークフローを一括でSHAピン留めに変換できます。手動での書き換えが多い場合に有効です。

SHAピン留めは「コードの不変性」を保証しますが、脆弱性修正の適用が遅れるリスクがあります。Dependabotの設定と組み合わせて、更新PRを定期的にレビューする運用を必ずセットで導入してください。

2. npm/PyPIの依存関係監査

npm auditpip-auditを定期的に実行し、既知の脆弱性を検出します。加えて、ロックファイル(package-lock.jsonpoetry.lockなど)の変更差分を常に確認してください。

今日すぐ実行できる監査コマンド

# --- npm ---

# 脆弱性チェック(全件)
npm audit

# high以上の脆弱性のみ表示
npm audit --audit-level=high

# 修正可能な脆弱性を自動修正
npm audit fix

# 本番依存のみ監査(devDependenciesを除外)
npm audit --omit=dev

# JSON形式で出力(CIでのパース用)
npm audit --json

# lockfileの整合性確認(package.jsonとlockfileの不整合を検出)
npm ci --ignore-scripts  # lockfileと一致しなければエラー、scriptsは安全のため無効化
# --- Python ---

# pip-auditのインストールと実行
pip install pip-audit
pip-audit

# requirements.txtを直接監査
pip-audit -r requirements.txt

# Poetry環境の監査(requirements.txtにエクスポートしてから実行)
poetry export -f requirements.txt --output requirements-audit.txt
pip-audit -r requirements-audit.txt

# JSON形式で出力
pip-audit -f json
# --- Socket.dev CLI(より高度な検出) ---

# Socket CLIはtyposquatting等の振る舞いベースの検出が可能
npx socket scan create --repo . --type npm

CIに監査を組み込む

# .github/workflows/audit.yml
name: Dependency Audit
on:
  pull_request:
    paths:
      - 'package-lock.json'
      - 'package.json'
      - 'requirements*.txt'
      - 'poetry.lock'

jobs:
  npm-audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
      - run: npm audit --audit-level=high

  pip-audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
      - uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v5
        with:
          python-version: '3.12'
      - run: pip install pip-audit && pip-audit -r requirements.txt

さらに踏み込んだ対策として、以下を検討してください。

  • Socket.devSnyk などのサプライチェーン監視ツールの導入
  • postinstallスクリプトの無効化(信頼できないパッケージの場合)
  • プライベートレジストリの利用とスコープ設定
# postinstallスクリプトを無効化してインストール
npm install --ignore-scripts <package-name>

# その後、必要に応じて手動でスクリプトを実行
npm rebuild <package-name>

3. AIエージェントスキルの導入前チェックリスト

AIエージェントにサードパーティのスキルやプラグインを追加する前に、以下の項目を確認します。ClawHubでは登録スキルの約12%が悪意あるものだったという事実を踏まえると、「公式レジストリにあるから安全」という前提は成り立ちません。

リポジトリの信頼性を検証する

チェック項目 確認方法
リポジトリの所有者は実在するか GitHubプロフィールの活動履歴を確認
所有者のアカウント作成日は最近すぎないか GitHub APIでcreated_atを確認
参照URLにリダイレクトはないか curl -I <url> でHTTPステータスを確認
リポジトリにリダイレクト(名前変更の痕跡)はないか curl -sI でリダイレクト有無を確認
# リポジトリのリダイレクト確認(リダイレクトがあればrepojackingの兆候)
curl -sI https://github.com/<owner>/<repo> | grep -i location

# GitHub APIで所有者情報を確認
gh api repos/<owner>/<repo> --jq '{
  owner: .owner.login,
  owner_id: .owner.id,
  created: .created_at,
  updated: .updated_at,
  stars: .stargazers_count,
  archived: .archived
}'

# 所有者のアカウント作成日を確認(新しすぎるアカウントは要注意)
gh api users/<owner> --jq '{login: .login, created_at: .created_at, public_repos: .public_repos}'

スキルのコード内容を検証する

チェック項目 確認方法
コードの内容を読んだか スキル定義ファイルを目視で確認
外部URLへの通信はないか コード内のfetchhttpcurl等を検索
最小権限の原則を満たしているか 要求されるパーミッションが妥当か検証
スキル説明文にプロンプトインジェクションはないか 説明文に隠し指示がないか確認

AIエージェントのスキルは、ツール説明文がLLMのプロンプトに直接注入されます。悪意ある説明文が含まれている場合、エージェントの動作が乗っ取られる可能性があります。スキルのソースコードだけでなく、メタデータ(name、description、instructions等)も必ず確認してから導入してください。

署名と来歴を検証する(可能な場合)

# GitのコミットにGPG署名があるか確認
gh api repos/<owner>/<repo>/commits --jq '.[0] | {sha: .sha, verified: .commit.verification.verified, reason: .commit.verification.reason}'

# npm パッケージの署名を検証
npm audit signatures

4. CI/CDシークレットのローテーション

Trivyインシデントのような場合、影響を受けた可能性があるシークレットは即座にローテーションする必要があります。

対象となるシークレットの例です。

  • クラウドプロバイダの認証情報(AWS、GCP、Azure)
  • コンテナレジストリのトークン
  • npmやPyPIの公開トークン
  • GitHub Personal Access Token
  • Slack Webhook URLやAPIキー
# GitHub Actionsで使用中のシークレット一覧を確認
gh secret list --repo <owner>/<repo>

# 新しいシークレットを設定
gh secret set <SECRET_NAME> --repo <owner>/<repo>

シークレットのローテーション後は、依存するワークフローやデプロイメントが正常に動作することを必ず確認してください。ローテーション漏れを防ぐため、シークレットの棚卸しリストを作成しておくことを推奨します。

5. 追加の防御レイヤー

上記4つの対策に加え、組織的な防御策も検討してください。

# GitHub Actionsでのネットワークアクセス制限例
# (GitHub-hosted runnersでは制限あり、self-hostedでより柔軟)
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read  # 最小権限の原則
      packages: read
    steps:
      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
  • GitHub Actionsのpermissionsを明示的に設定し、GITHUB_TOKENの権限を最小化する
  • CODEOWNERSファイルで.github/workflows/の変更にレビューを必須にする
  • GitHub Advanced SecurityのSecret scanningを有効にする
  • StepSecurity Harden-RunnerでCI/CDランナーのネットワーク通信を監視する
# .github/CODEOWNERS
/.github/workflows/ @security-team

CI/CDセキュリティ健全性チェックリスト

自分のプロジェクトがどの程度防御できているか、以下のチェックリストで確認してみてください。

GitHub Actions

  • すべてのサードパーティActionsがコミットSHAでピン留めされている
  • Dependabotがgithub-actionsエコシステムに対して有効になっている
  • ワークフローのpermissionsが明示的に最小権限で設定されている
  • .github/workflows/ディレクトリがCODEOWNERSでレビュー必須になっている
  • Secret scanningが有効になっている

依存パッケージ

  • npm auditpip-auditがCIパイプラインに組み込まれている
  • ロックファイルの変更がPRレビューで確認されている
  • 不要なpostinstallスクリプトが無効化されている
  • 依存パッケージの更新PRが定期的にレビューされている

シークレット管理

  • CI/CDで使用するシークレットの棚卸しリストが存在する
  • シークレットに有効期限が設定されている(または定期ローテーションの運用がある)
  • PATの代わりにGitHub Appトークンやfine-grained PATを使用している
  • ワークフローログにシークレットが出力されていないことを確認済み

AIエージェント

  • サードパーティスキル導入時にリポジトリの信頼性を検証している
  • スキルの要求パーミッションが最小権限になっている
  • AIエージェントが自動インストールするパッケージに承認フローがある
  • MCPサーバーの接続先が意図したものであることを確認している

すべての項目にチェックが入らなくても問題ありません。まずは「GitHub ActionsのSHAピン留め」と「dependencyの監査のCI組み込み」の2つから始めるだけで、防御力は大きく向上します。

まとめ

2026年3月のインシデントが示しているのは、サプライチェーン攻撃の対象が拡大し続けているという事実です。パッケージレジストリからCI/CD、さらにAIエージェントのスキル定義へと、開発者が暗黙的に信頼するレイヤーが次々と狙われています。

攻撃の規模も無視できないレベルに達しています。ReversingLabsの報告では前年比73%増、Sonatypeの集計では年間45万件超の悪意あるパッケージが確認されています。AIエージェントのスキルレジストリでは登録スキルの約12%が悪意あるものだったという報告もあります。

防御は「気づくこと」から始まります。今回の記事で挙げた対策を振り返ります。

  1. GitHub ActionsをコミットSHAでピン留めする
  2. 依存パッケージの監査をCIパイプラインに組み込む
  3. AIエージェントスキルの導入前にリポジトリの信頼性とコード内容を検証する
  4. CI/CDシークレットを定期的にローテーションする
  5. ワークフローの権限を最小化する
  6. チェックリストで自分のプロジェクトの健全性を定期的に確認する

これらはいずれも、特別なツールや予算を必要としない基本的な対策です。自分のパイプラインが侵害されたと仮定して、一度棚卸しをしてみてください。

参考リンク

12
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?