Trivy で Terraform のミスコンフィギュレーションを検知する: Checkov との比較デモ
前回の記事で、Checkov を使った Terraform 脆弱性検知のデモリポジトリを作成しました。今回は同じ Terraform コードに対して Trivy でスキャンし、ツール間の検知結果を比較します。
Trivy は Aqua Security が開発するオープンソースのセキュリティスキャナです。コンテナイメージのスキャンで広く知られていますが、Terraform、CloudFormation、Kubernetes マニフェストなどの IaC ミスコンフィギュレーション検知にも対応しています。
デモリポジトリ: codenote-net/trivy-terraform-demo
Checkov との違い
同じ Terraform コードをスキャンしても、Checkov と Trivy では検知結果が異なります。先にツール間の主な違いを整理しておきます。
| 項目 | Checkov | Trivy |
|---|---|---|
| 開発元 | Prisma Cloud (Palo Alto Networks) | Aqua Security |
| チェック ID 体系 | CKV_AWS_XXX, CKV2_AWS_XXX | AVD-AWS-XXXX |
| severity 分類 | PASSED / FAILED の 2 値 | CRITICAL / HIGH / MEDIUM / LOW の 4 段階 |
| インストール | pip install checkov | brew install trivy |
| スキャンコマンド | checkov -d <dir> | trivy config <dir> |
| 対応範囲 | IaC 特化 | コンテナイメージ、ファイルシステム、IaC、SBOM など幅広い |
| カスタムポリシー | Python | Rego (OPA) |
| GitHub Actions | bridgecrewio/checkov-action | aquasecurity/trivy-action |
最大の違いは severity の扱いです。Checkov は PASSED か FAILED の 2 値ですが、Trivy は各検知結果に CRITICAL / HIGH / MEDIUM / LOW の severity を割り当てます。これにより、対応の優先順位がつけやすくなります。
デモリポジトリの構成
Checkov 版と同じ構成で、insecure/ に脆弱なコード、secure/ に修正済みコードを配置しています。
trivy-terraform-demo/
├── insecure/ # 意図的に脆弱な Terraform コード
│ ├── provider.tf
│ ├── s3.tf
│ ├── sg.tf
│ ├── rds.tf
│ ├── iam.tf
│ └── cloudtrail.tf
├── secure/ # 修正済みの Terraform コード
│ ├── provider.tf
│ ├── s3.tf
│ ├── sg.tf
│ ├── rds.tf
│ ├── iam.tf
│ └── cloudtrail.tf
└── .github/workflows/
└── trivy.ymlTerraform コードは checkov-terraform-demo と同一です。実装の詳細は PR #1 で確認できます。
Trivy でスキャンする
Trivy のインストールは Homebrew で行います。
brew install trivyinsecure/ ディレクトリに対してスキャンを実行します。
trivy config insecure/Terraform のみに限定する場合は --misconfig-scanners フラグを使います。
trivy config --misconfig-scanners terraform insecure/severity でフィルタリングすることもできます。
trivy config --severity HIGH,CRITICAL insecure/Checkov ではデフォルトで PASSED も表示されますが、Trivy はデフォルトで FAILURES のみを表示します。PASSED も含めて全結果を見たい場合は --include-non-failures フラグを指定します。
trivy config --include-non-failures insecure/検知結果: 27 FAILURES
Trivy v0.69.3 でのスキャン結果は 27 FAILURES でした。Checkov の 37 件と比べて 10 件少なくなっています。
リソース別に検知結果を見ていきます。Trivy は各検知に severity を割り当てるため、テーブルに severity 列を追加しています。
S3: 11 件(CRITICAL 1 / HIGH 6 / MEDIUM 1 / LOW 3)
| AVD ID | Severity | 内容 |
|---|---|---|
| AVD-AWS-0086 | HIGH | パブリック ACL をブロックしていない |
| AVD-AWS-0087 | HIGH | パブリックポリシーをブロックしていない |
| AVD-AWS-0089 | LOW | アクセスログが無効 |
| AVD-AWS-0090 | MEDIUM | バージョニングが無効 |
| AVD-AWS-0091 | HIGH | パブリック ACL を無視していない |
| AVD-AWS-0092 | HIGH | パブリック ACL(public-read)が設定されている |
| AVD-AWS-0093 | HIGH | パブリックバケットを制限していない |
| AVD-AWS-0094 | LOW | パブリックアクセスブロックが未設定 |
| AVD-AWS-0132 | HIGH | カスタマーマネージドキーで暗号化されていない |
| AVD-AWS-0161 | CRITICAL | CloudTrail の S3 バケットが公開されている |
| AVD-AWS-0163 | LOW | CloudTrail の S3 バケットのログが無効 |
Checkov では S3 に対して 8 件の検知でした。Trivy は S3 のパブリックアクセスブロックの各設定項目(block_public_acls、block_public_policy、ignore_public_acls、restrict_public_buckets)を個別にチェックするため、件数が多くなっています。また、CloudTrail が参照する S3 バケットの公開状態(AVD-AWS-0161)を CRITICAL として検知しているのが特徴的です。
Security Group: 6 件(CRITICAL 1 / HIGH 2 / LOW 3)
| AVD ID | Severity | 内容 |
|---|---|---|
| AVD-AWS-0104 | CRITICAL | 全 IP アドレスへの無制限な Egress |
| AVD-AWS-0107 | HIGH | 全ポートが 0.0.0.0/0 に開放(2 件) |
| AVD-AWS-0124 | LOW | ルールに description がない(3 件) |
Checkov でも Security Group は 6 件でした。ただし、Checkov は SSH(CKV_AWS_24)、RDP(CKV_AWS_25)、HTTP(CKV_AWS_260)と特定ポートごとにチェックするのに対し、Trivy は AVD-AWS-0107 で包括的にチェックしています。
RDS: 6 件(HIGH 2 / MEDIUM 3 / LOW 1)
| AVD ID | Severity | 内容 |
|---|---|---|
| AVD-AWS-0077 | MEDIUM | バックアップ保持期間が短い |
| AVD-AWS-0080 | HIGH | ストレージ暗号化が無効 |
| AVD-AWS-0133 | LOW | Performance Insights が無効 |
| AVD-AWS-0176 | MEDIUM | IAM データベース認証が無効 |
| AVD-AWS-0177 | MEDIUM | 削除保護が無効 |
| AVD-AWS-0180 | HIGH | パブリックアクセスが有効 |
Checkov の 9 件に対して Trivy は 6 件です。Checkov が検知する Enhanced Monitoring(CKV_AWS_118)、CloudWatch Logs 出力(CKV_AWS_129)、Multi-AZ(CKV_AWS_157)は Trivy では検知されません。一方、Trivy はバックアップ保持期間(AVD-AWS-0077)と Performance Insights(AVD-AWS-0133)を追加で検知しています。
CloudTrail: 4 件(HIGH 2 / MEDIUM 1 / LOW 1)
| AVD ID | Severity | 内容 |
|---|---|---|
| AVD-AWS-0014 | MEDIUM | 全リージョンで有効化されていない |
| AVD-AWS-0015 | HIGH | カスタマーマネージドキーで暗号化されていない |
| AVD-AWS-0016 | HIGH | ログファイルのバリデーションが無効 |
| AVD-AWS-0162 | LOW | CloudWatch Logs が未設定 |
Checkov の 5 件に対して Trivy は 4 件です。Checkov が検知する SNS トピック未設定(CKV_AWS_252)は Trivy では検知されません。
IAM: 0 件
ここが最も大きな違いです。Checkov は IAM ワイルドカードポリシー(Action: "*", Resource: "*")に対して 9 件の FAILED を検知しましたが、Trivy v0.69.3 は 1 件も検知しませんでした。
Checkov は権限昇格(CKV_AWS_286)、認証情報の露出(CKV_AWS_287)、データ持ち出し(CKV_AWS_288)など、ワイルドカードポリシーから派生するリスクを細かく分析します。Trivy はこの領域のチェックが手薄で、IAM ポリシーの過剰な権限は検知対象外となっています。
IAM のセキュリティを重視する場合は、Trivy 単体では不十分であり、Checkov や IAM Access Analyzer との併用が推奨されます。
検知数の比較サマリ
| リソース | Checkov | Trivy | 差分 |
|---|---|---|---|
| S3 | 8 | 11 | Trivy +3 |
| Security Group | 6 | 6 | 同数 |
| RDS | 9 | 6 | Checkov +3 |
| IAM | 9 | 0 | Checkov +9 |
| CloudTrail | 5 | 4 | Checkov +1 |
| 合計 | 37 | 27 | Checkov +10 |
修正済みコードのスキャン結果
trivy config secure/結果は 0 FAILURES でした。Checkov 版と同じ修正コードで、Trivy のチェックもすべてパスしています。
GitHub Actions で CI に組み込む
aquasecurity/trivy-action を使って、PR ごとに Trivy を自動実行します。
name: Trivy
on:
push:
branches: [main]
paths:
- "insecure/**"
- "secure/**"
- ".github/workflows/trivy.yml"
pull_request:
branches: [main]
paths:
- "insecure/**"
- "secure/**"
- ".github/workflows/trivy.yml"
permissions:
contents: read
pull-requests: write
jobs:
scan-insecure:
name: "Scan insecure/"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy on insecure/
uses: aquasecurity/trivy-action@0.35.0
with:
scan-type: config
scan-ref: insecure/
format: table
exit-code: "0"
severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
hide-progress: true
scan-secure:
name: "Scan secure/"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy on secure/
uses: aquasecurity/trivy-action@0.35.0
with:
scan-type: config
scan-ref: secure/
format: table
exit-code: "1"
severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
hide-progress: trueCheckov 版との違いは exit-code の使い方です。Checkov は soft_fail: true/false で CI の成否を制御しますが、Trivy は exit-code で制御します。"0" なら FAILURES があっても CI を通し、"1" なら CI を落とします。
まとめ
同じ Terraform コードに対して Checkov は 37 件、Trivy は 27 件の検知でした。件数だけを見れば Checkov のほうが網羅的ですが、それは必ずしも「Checkov のほうが優れている」ことを意味しません。
ツール選定のポイントは以下です。
- IAM ポリシーの監査が重要なら Checkov: Trivy は IAM ワイルドカードを検知しない
- severity で優先順位をつけたいなら Trivy: CRITICAL / HIGH / MEDIUM / LOW の分類がある
- コンテナイメージも一緒にスキャンしたいなら Trivy: 1 つのツールで IaC とコンテナの両方をカバーできる
- 両方使うのが理想: チェック範囲が異なるため、併用することで網羅性が上がる
どちらのツールも terraform init 不要で、CI への導入コストは低いです。まずは一方を導入し、カバレッジの不足を感じたらもう一方を追加する、という進め方がおすすめです。
- Trivy デモリポジトリ: codenote-net/trivy-terraform-demo
- Checkov デモリポジトリ: codenote-net/checkov-terraform-demo
- Trivy: aquasecurity/trivy
- Trivy ドキュメント: trivy.dev
- Aqua Vulnerability Database: avd.aquasec.com/misconfig
以上、Checkov と Trivy の二刀流でいきたい、現場からお送りしました。