コンテナイメージの87%に重大度High以上の脆弱性が含まれているという調査結果があります(出典: Sysdig 2023 Cloud-Native Security and Usage Report)。Docker化・Kubernetes化が加速する現代のインフラでは、アプリケーションコードだけを守っても不十分です。ベースイメージやOSパッケージに潜む脆弱性が攻撃者の侵入口になります。

本記事は、コンテナ脆弱性スキャンをはじめて導入するエンジニアから、既存のCI/CDパイプラインに組み込もうとしているSREまでを対象に、ツール選定・設定・運用上の判断基準を一冊にまとめたリファレンスです。


コンテナ環境で脆弱性スキャンが求められる背景

コンテナは「動いているもの」ではなく「パッケージされたもの」です。Dockerイメージは複数のレイヤーで構成され、ベースイメージに含まれるOSパッケージ、言語ランタイム、依存ライブラリがすべて内包されます。開発者がアプリケーションコードを一行も変更していなくても、ベースイメージ内のOpenSSLやlibcに新たなCVEが登録された瞬間から、そのコンテナは脆弱になります。

ベースイメージからの脆弱性継承とレイヤー問題

FROM ubuntu:22.04 と書いた時点で、そのUbuntu 22.04に含まれる数百のOSパッケージがイメージに取り込まれます。ベースイメージを月に一度しか更新しない運用では、その間に公開されたCVEがすべて本番環境に残り続けます。さらに RUN apt-get install python3-pip のような命令を追加するたびに新たなレイヤーが積み重なり、それぞれのレイヤーが脆弱性の温床になります。

コンテナ固有の脅威モデル:6つの攻撃ベクター

海外のセキュリティ研究者が整理した脅威モデルでは、コンテナ環境への攻撃は以下の6経路に分類されます。

攻撃ベクター具体的リスク対策手段
脆弱なコード・ライブラリ既知CVEを持つパッケージの悪用脆弱性スキャン
侵害されたベースイメージマルウェア埋め込みイメージの利用イメージ署名検証
ランタイム設定ミスprivilegedコンテナ、root実行IaCスキャン・CIS Benchmark
シークレット露出環境変数・イメージへの認証情報混入シークレットスキャン
不安全なネットワークコンテナ間の無制限通信NetworkPolicy
コンテナ脱出ホストへのroot権限取得(例:CVE-2019-5736)カーネルパッチ・非rootコンテナ

コンテナ脱出の代表例であるCVE-2019-5736は、runcの脆弱性を突いてコンテナ内プロセスがホストのruncバイナリを書き換え、ホストrootを取得できる攻撃です(CVSS: 8.6)。また、侵害コンテナを踏み台にしてホストのCPUリソースを暗号通貨マイニングに使う「クリプトジャッキング」もコンテナ固有の実害として報告されています。


コンテナ脆弱性スキャンの仕組みと対象範囲

コンテナスキャンとは何ですか?

コンテナスキャンとは、コンテナイメージを構成するすべてのソフトウェアコンポーネント(OSパッケージ、言語ライブラリ、設定ファイルなど)を自動的に解析し、既知の脆弱性データベースと照合してセキュリティ上の問題を検出するプロセスです。動作中のプロセスを検査するものではなく、イメージそのものを静的に分析します。

CVE/NVDデータベースとの照合プロセス

スキャナはイメージのレイヤーを展開し、インストール済みパッケージの一覧を抽出します。その一覧をNVD(National Vulnerability Database)や各ディストリビューションのセキュリティアドバイザリ(Ubuntu Security Notices、Red Hat Errata等)と照合し、マッチした項目をCVE IDとともに報告します。

flowchart LR
    A["コンテナイメージ\n(.tar / レジストリ)"] --> B["レイヤー展開\nパッケージ一覧抽出"]
    B --> C["SBOM生成\n(部品表)"]
    C --> D["脆弱性DB照合\nNVD / Advisory"]
    D --> E["レポート出力\nCRITICAL/HIGH/MEDIUM/LOW"]
    E --> F{"閾値超過?"}
    F -->|Yes| G["ビルド失敗\nアラート通知"]
    F -->|No| H["次工程へ"]

スキャン対象の4カテゴリ

現代のスキャナが対象とするのはOSパッケージだけではありません。

  • OSパッケージ: apt/yum/apkで管理されるバイナリ
  • 言語別ライブラリ: requirements.txt(Python)、package.json(Node.js)、go.sum(Go)、pom.xml(Java)など
  • IaCファイル: Dockerfile、Terraformファイル、Helmチャート(設定ミスの検出)
  • シークレット: イメージに誤って含まれたAPIキー、パスワード、証明書

スキャンを実行すべき5つのタイミング

脆弱性スキャンの目的は何ですか?

脆弱性スキャンの目的は、攻撃者が悪用できるセキュリティ上の弱点を事前に発見し、インシデント発生前に修正することです。コンテナ環境では「いつスキャンするか」で検出できる脅威の種類と対応コストが変わります。

タイミング検出対象推奨ツール対応コスト
開発時(ローカルビルド)新たに追加したパッケージの脆弱性Trivy, Docker Scout低(即時修正可)
ビルド時(CI push)イメージ全体の脆弱性・IaCミスTrivy, Grype低〜中
レジストリプッシュ後継続監視・新規CVE検出ECR拡張スキャン, Docker Hub中(非同期対応)
デプロイ前(Admission Controller)脆弱イメージのクラスタ流入阻止OPA Gatekeeper, Kyverno中(自動ブロック)
ランタイム時コンテナ脱出・異常プロセス検知Falco, Sysdig Secure高(インシデント対応)

特に競合記事でカバーされていない「デプロイ前のAdmission Controller」は重要です。KubernetesのAdmission Controllerを使えば、スキャンで一定以上の重大度CVEが検出されたイメージを kubectl apply 時点で自動拒否できます。OPA GatekeeperやKyvernoのポリシーとTrivyを組み合わせることで、開発者がどれだけセキュリティを意識していなくても本番クラスタへの侵入を防ぐ「防衛線」を設けられます。


主要スキャンツールの機能とコスト比較

ツール選定マトリクス

ツール名開発元ライセンス主な対応対象CI/CD連携SBOM対応特記事項
TrivyAqua SecurityApache 2.0OS・言語ライブラリ・IaC・コンテナ・VMGitHub Actions公式Action有SPDX/CycloneDX最も対象範囲が広いOSS
Docker ScoutDocker Inc.商用(無料枠あり)コンテナイメージ・SBOMDocker CLI統合・GitHub ActionsCycloneDXDocker Hub/Desktopとネイティブ統合
GrypeAnchoreApache 2.0コンテナ・SBOM・ファイルシステム公式Action有SPDX/CycloneDXFP削減に強みあり・EPSS対応
Snyk ContainerSnyk商用(無料枠あり)コンテナ・IaC・OSS依存GitHub/GitLab/JenkinsCycloneDX修正PRの自動提案
ClairCoreOS(現Red Hat)Apache 2.0OSパッケージ中心API経由で統合非対応セルフホスト向け・やや古め
Anchore EnterpriseAnchore商用コンテナ・SBOM・コンプライアンスJenkins/GitLab等SPDX/CycloneDX商用版Grype+ポリシーエンジン
Sysdig SecureSysdig商用コンテナ・Kubernetes・ランタイムCI/CD全般CycloneDXランタイム保護も一体化
yamoryアシュアード商用OSS脆弱性全般(コンテナ含む)主要CI対応対応日本語サポート・国内法令対応

OSSと商用の使い分け指針

小規模チームや個人開発では Trivy または Grype から始めるのが最善です。無料でフル機能を使えます。チーム規模が拡大し「脆弱性対応ワークフローの管理」「コンプライアンスレポート」「修正提案の自動化」が必要になった段階で Snyk Container や Anchore Enterprise への移行を検討してください。国内のSLAや日本語サポートを重視するなら yamory が選択肢に入ります。

Docker Scoutについて

Docker Scout(検索ボリューム22,200)はDocker社が提供するネイティブのサプライチェーンセキュリティツールです。docker scout cves <イメージ名> コマンドだけで脆弱性一覧を取得でき、Docker DesktopのUIからも確認できます。無料のPersonalプランでは1リポジトリまで継続的な脆弱性分析が可能で、Team/Businessプランから無制限リポジトリの監視に対応します(2024年12月プラン改定後)(出典: Docker Scout公式)。


Trivy によるコンテナイメージスキャンの手順

Trivyは「トリヴィ」と読みます(tri は trigger の tri、vy は envy の vy)。Aqua Securityが開発しオープンソースとして公開している脆弱性スキャナで、コンテナイメージ・ファイルシステム・Git リポジトリ・Kubernetes クラスタ・IaCファイルと、最も広範なスキャン対象をカバーします。

インストール方法

# Homebrew(macOS/Linux)
brew install trivy

# apt(Ubuntu/Debian)
sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update && sudo apt-get install trivy

# Docker経由(インストール不要)
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy:latest image nginx:latest

基本スキャンコマンド

# Dockerイメージをスキャン
trivy image nginx:latest

# HIGH・CRITICAL のみ表示(LOW/MEDIUMはスキップ)
trivy image --severity HIGH,CRITICAL nginx:latest

# JSON形式で出力(CI連携時)
trivy image --format json --output result.json nginx:latest

# ローカルDockerfileとIaCをスキャン
trivy config ./

# ファイルシステムをスキャン(requirements.txtなど)
trivy fs ./

スキャン結果の読み方

Trivy スキャン結果の出力例 — Library・CVE・Severity・バージョン情報を含むテーブル形式
  • CRITICAL/HIGH: 即座の対応を検討。Fixed Versionが存在すればベースイメージ更新またはパッケージアップデート
  • MEDIUM: スプリントサイクル内での対応を計画
  • LOW: バックログに積んで次回のイメージ更新時に対処

誤検知(False Positive)の除外

# .trivyignore ファイルを作成してCVEを除外
cat > .trivyignore << 'EOF'
# 対応不要と判断したCVE(理由を必ずコメントで記載)
CVE-2023-1234  # ベンダー公式で影響なしと確認済み(2024-01-15)
CVE-2023-5678  # Distroless環境のため当該機能が存在しない
EOF

trivy image --ignorefile .trivyignore nginx:latest

SBOMの生成

SBOM(ソフトウェア部品表)は、イメージに含まれる全コンポーネントの目録です。SPDX形式で生成しておくと、後から新しいCVEが公開された際に「自社イメージへの影響有無を即座に判定」できます。

# SPDX-JSON形式でSBOM生成
trivy image --format spdx-json --output sbom.spdx.json nginx:latest

# CycloneDX形式でSBOM生成
trivy image --format cyclonedx --output sbom.cyclonedx.json nginx:latest

# 既存のSBOMから脆弱性スキャン(再スキャン不要)
trivy sbom sbom.spdx.json

GitHub Actions を使ったスキャンの自動化

GitHub ActionsへのTrivy統合は、PRのたびに脆弱性チェックを自動実行し、結果をGitHub Security Advisoriesに連携できます。競合記事の多くがTravis CIやCircleCIの例のみを掲載しているのに対し、現在の標準はGitHub Actionsです。

基本ワークフロー(PRごとにスキャン実行)

# .github/workflows/trivy.yml
name: Container Vulnerability Scan

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  trivy-scan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write  # GitHub Security tabへの書き込みに必要

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Build Docker image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          format: sarif
          output: trivy-results.sarif
          severity: CRITICAL,HIGH
          exit-code: 1  # CRITICAL/HIGH検出時にビルド失敗

      - name: Upload results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v3
        if: always()  # スキャン失敗時も結果をアップロード
        with:
          sarif_file: trivy-results.sarif

ECRへのプッシュと連携したスキャン

AWSのECR(Elastic Container Registry)では、イメージプッシュ時に自動スキャンを有効化できます(ECR基本スキャン)。さらに ECR拡張スキャン(Amazon Inspector連携)を有効にすると、OS脆弱性に加えてプログラミング言語パッケージの脆弱性も継続的に監視されます。

      - name: Push to ECR with scan
        env:
          AWS_REGION: ap-northeast-1
        run: |
          aws ecr get-login-password --region $AWS_REGION | \
            docker login --username AWS --password-stdin \
            ${{ secrets.ECR_REGISTRY }}
          docker tag myapp:${{ github.sha }} \
            ${{ secrets.ECR_REGISTRY }}/myapp:${{ github.sha }}
          docker push ${{ secrets.ECR_REGISTRY }}/myapp:${{ github.sha }}
          # ECR拡張スキャンの結果確認(プッシュ後に非同期実行)
          aws ecr wait image-scan-complete \
            --repository-name myapp \
            --image-id imageTag=${{ github.sha }}

CVSSスコアの読み方と脆弱性対応の優先順位

CVSSv3(Common Vulnerability Scoring System v3)のスコアは0.0〜10.0で表され、3つのスコアグループから構成されます。

  • Base Score: 脆弱性そのものの固有特性(攻撃経路、権限要件、影響範囲)
  • Temporal Score: エクスプロイトコードの公開状況、修正の有無
  • Environmental Score: 自組織の環境・重要度を加味した調整値
CVSSv3スコア深刻度実務での緊急度
9.0 〜 10.0CRITICAL即日対応(SLA: 24〜72時間)
7.0 〜 8.9HIGH1週間以内
4.0 〜 6.9MEDIUM次スプリント内
0.1 〜 3.9LOWバックログ管理

スコアだけで優先順位を決めると「スコアは高いが自社システムには影響しない」脆弱性に時間を取られます。実務での判断フローは以下のとおりです。

flowchart TD
    A["CVE検出"] --> B{"CVSS Base\n≥ 7.0?"}
    B -->|No| C["MEDIUM以下\nバックログへ"]
    B -->|Yes| D{"当該パッケージ\nランタイムで使用?"}
    D -->|No| E["重要度を下げて\n次イメージ更新時に対処"]
    D -->|Yes| F{"エクスプロイト\nコード公開済?"}
    F -->|Yes| G["即日対応\nベースイメージ更新"]
    F -->|No| H{"Fixed Version\n存在する?"}
    H -->|Yes| I["1週間以内に\nパッケージ更新"]
    H -->|No| J["WorKaroundを適用\n監視強化"]

Trivyの結果には「ランタイムで使用されているか」の情報が含まれるため、実際に脆弱なコードパスが実行されるかどうかを判断材料にできます。Sysdig社の調査では、重大/高深刻度の脆弱性のうちランタイムで実際に使用されているパッケージに存在するものは15%程度にとどまると報告されています(出典: Sysdig 2023 Cloud-Native Security and Usage Report)。


SBOMとコンテナスキャンを組み合わせたサプライチェーン防御

SBOMとは

SBOM(Software Bill of Materials:ソフトウェア部品表)は、ソフトウェアに含まれるすべてのコンポーネント・依存関係・ライセンスを機械可読な形式で記述したドキュメントです。主要なフォーマットは2つあります。

  • SPDX(Software Package Data Exchange): Linux Foundation主導。ライセンスコンプライアンス用途にも強い
  • CycloneDX: OWASP主導。セキュリティ用途(脆弱性管理・VEX連携)に特化

SolarWinds攻撃(2020年)に代表されるソフトウェアサプライチェーン攻撃への対策として、米国政府は連邦政府向けソフトウェアプロバイダへのSBOM提供を義務化しました(大統領令EO 14028、2021年)。企業のコンテナ運用においてもSBOMは「資産台帳」として機能します。

TrivyによるSBOM生成とスキャン統合

# ビルド時にSBOMを生成(CI/CDに組み込む)
trivy image --format spdx-json --output sbom.spdx.json myapp:latest

# SBOMを保管しておき、後日新CVE発表時に再スキャン
trivy sbom sbom.spdx.json --severity CRITICAL,HIGH

# TerraformファイルのIACスキャン(Trivy Terraform)
trivy config ./terraform/
# Dockerfile・Helmチャートも同じコマンドで対応
trivy config ./k8s/

Trivy Terraform(IaCスキャン)機能を使えば、Terraformコードに含まれる設定ミス(S3バケットのパブリックアクセス許可、セキュリティグループの0.0.0.0/0開放など)をコード段階で検出できます。

PythonライブラリのSBOM管理

Python(python 脆弱性、Python Bandit関連KW)の依存管理においても、requirements.txtやPipfile.lockをTrivyでスキャンできます。

# Pythonプロジェクトの依存脆弱性チェック
trivy fs --scanners vuln,secret ./

# Python Bandit(静的解析)と組み合わせてコード脆弱性も検出
pip install bandit
bandit -r ./src/

運用で直面しやすい課題と解決策

誤検知(False Positive)への対処

大規模なコンテナ環境では一度のスキャンで数百件のCVEが検出されることがあります。その中には「ベンダーが影響なしと公式回答しているが、データベース上では検出される」ケースが多数含まれます。

対処フローを組織として統一しておくことが重要です。

  1. CVEの精査: NVDのDescriptionと影響するコンポーネントを確認
  2. ベンダーアドバイザリの確認: UbuntuならUbuntu Security NoticesでFixedバージョンを確認
  3. 除外ルールの文書化: .trivyignore に理由と確認日をコメントで記載
  4. VEX(Vulnerability Exploitability eXchange)の活用: TrivyはCycloneDX VEX形式でFPを除外設定できる

アラート疲労(Alert Fatigue)への対応

スキャン結果を全件Slackに通知するのは「通知を無視する文化」を作るだけです。以下の設計を推奨します。

  • CIゲート: CRITICALのみビルド失敗
  • 週次レポート: HIGH以上を週1回集計してチームに共有
  • ダッシュボード: GrafanaやDefectDojo等で可視化・トレンド管理

Distrolessイメージでのスキャン注意点

GoogleのDistrolessイメージはシェルや汎用ユーティリティを取り除いたミニマルイメージです。攻撃対象面積は大きく削減されますが、aptdpkgデータベースが存在しないためスキャナによっては検出精度が落ちます。TrivyはDistrolessに対応していますが、スキャン結果が「0件」でも安全確認の代わりにはなりません。OSパッケージの脆弱性より言語ライブラリ(requirements.txt等)への注意が必要です。

脆弱性削減KPIの設定

セキュリティ施策の効果を測定するため、以下のKPIを設定することを推奨します。

KPI定義目標値の例
TTR(Time To Remediate)脆弱性検出から修正完了までの平均時間CRITICAL: 72時間以内
CRITICAL CVE削減率四半期ごとのCRITICAL件数の変化率前期比-30%
FP削減率誤検知率の改善(除外ルール整備で測定)-50%/半年
スキャンカバレッジCI/CDにスキャンを組み込んだリポジトリの割合100%

よくある質問

Q: コンテナスキャンとイメージスキャンは何が違いますか?

厳密な用語上の区分はありませんが、「イメージスキャン」はDockerイメージファイルの静的解析(レイヤー内のパッケージ検索)を指し、「コンテナスキャン」はより広義でランタイム中の動作監視やコンテナ設定の検査も含む場合があります。実務ではどちらも「コンテナイメージへの静的脆弱性検査」を指して使われることが多く、ツールによって呼称が異なります。

Q: 完全無料で使えるスキャンツールはどれですか?

TrivyGrype は機能制限なくフル活用できます。Docker Scoutは無料プランが5リポジトリまでの監視に制限されます。GitHub Container Registryにはネイティブのスキャン機能はなく、別途ツールが必要です。

Q: スキャン結果にCRITICALが出たら即座にデプロイを止めるべきですか?

CRITICALすべてがリリースブロックになるとは限りません。「当該パッケージがランタイムで実際に使われているか」「エクスプロイトコードが公開されているか」「Fixed Versionが存在するか」の3点で判断します。CIゲートにはCRITICALを設定しつつ、例外申請プロセス(.trivyignoreへの記載と承認フロー)を設けることで、ビジネス継続性とセキュリティを両立できます。

Q: PythonライブラリやDockerfileの脆弱性もチェックできますか?

Trivyは trivy fs ./ でrequirements.txt・Pipfile.lock(Python脆弱性)のスキャンに対応しています。Dockerfileの設定ミス(rootユーザーでの実行、最新タグの固定、秘密情報のADD等)は trivy config ./ で検出できます。Pythonコードの脆弱なパターンを静的解析したい場合はBandit(Python Bandit)を並行して使うことを推奨します。TrivyはBanditと組み合わせることでコード・依存関係・コンテナイメージを網羅的にカバーできます。


まとめ

コンテナ脆弱性スキャンは「1回やれば終わり」ではなく、開発・ビルド・レジストリ・デプロイ・ランタイムと各フェーズに継続的に組み込む仕組みが必要です。重要なポイントを整理します。

  • ツール選定: まずTrivyをCI/CDに組み込むことから始め、商用機能が必要になったらSnykやAnchor Enterpriseへ移行する段階的アプローチが現実的
  • スキャンタイミング: ビルド時スキャン+Admission Controllerによるデプロイ前ブロックの組み合わせが最も費用対効果が高い
  • SBOM活用: イメージビルド時にSBOMを生成・保管することで、後日発覚した脆弱性への影響調査が数分で完了する
  • 優先順位付け: CVSSスコアだけでなく「ランタイムでの使用有無」「エクスプロイト公開状況」を加味して対応順序を決める
  • KPI管理: TTRやFP削減率でセキュリティ改善の進捗を定量化し、チームの努力を可視化する

コンテナセキュリティはDevSecOpsの要であり、脆弱性スキャンはその出発点です。Trivyの導入はコマンド1本から始められます。まず手元のDockerイメージに trivy image <イメージ名> を実行してみることが、組織のセキュリティ成熟度を高める最初の一歩です。