Claude CodeでTrivyを回して脆弱性を直す手順 — 再スキャンで閉じる
Trivyのimage・fs・configの結果をJSONでClaude Codeに渡し、修正後に再スキャンして閉じる手順。exit-code、.trivyignore.yamlでの誤検知の扱い、権限設定まで。
Trivyのスキャン結果は、JSONファイルに出力してClaude Codeに読ませ、修正したら同じコマンドで再スキャンして指摘が消えたことを確かめる、という往復で閉じられます。Claude Codeには「直す」役を、Trivyには「直ったかを判定する」役を持たせる分担です。
この記事では、コンテナイメージ・ファイルシステム・IaC(Dockerfile、Terraform、Kubernetesマニフェスト)の3種類のスキャンについて、結果の渡し方、再スキャンの終了コード、誤検知を .trivyignore.yaml で記録する方法、Claude Code側の権限設定を順に扱います。
Trivyのどのコマンドを回すか
Trivyは対象ごとにサブコマンドが分かれています。Claude Codeに渡す前に、何を調べたいかでコマンドを選びます。
| 調べたいもの | コマンド | 既定で有効なスキャナー |
|---|---|---|
| ビルド済みのコンテナイメージ | コマンドtrivy image | 既定で有効なスキャナー脆弱性・シークレット |
| プロジェクトの依存関係(ロックファイル) | コマンドtrivy fs | 既定で有効なスキャナー脆弱性・シークレット |
| Dockerfile・Terraform・Kubernetes等 | コマンドtrivy config | 既定で有効なスキャナー設定ミス(misconfiguration) |
trivy image と trivy fs の既定は脆弱性とシークレットの2つです。設定ミスの検出は --scanners misconfig を付けたときに有効になります。IaCだけを調べるなら trivy config が専用のコマンドで、ディレクトリを渡すとTerraform、CloudFormation、Kubernetes、Helm、Dockerfileが混在していても種類を自動判別します。
イメージに含まれるIaCファイルまで調べたいときは trivy image --scanners misconfig を使います。また --scanners vuln を指定すると脆弱性だけに絞れ、シークレット検出を外せるぶん速くなります。
結果をJSONでファイルに出す
Claude Codeに渡す形式は、表(table)よりJSONが向きます。表は人が読むための整形で、列が欠けたり折り返されたりします。JSONなら Results の下に対象ごとの Vulnerabilities が配列で入り、どのパッケージのどのバージョンをどこまで上げれば消えるかが項目として取れます。
trivy image -f json -o trivy-image.json \
--severity HIGH,CRITICAL myapp:latest出力されるJSONの Vulnerabilities には、VulnerabilityID、PkgName、InstalledVersion、Severity が必ず入ります。それ以外の項目は空のことがあります。公式の例では、libcrypto3 が InstalledVersion 3.3.2-r0で、FixedVersion が3.3.2-r1、Status が fixed と出ています。
修正の手がかりになるのは FixedVersion です。値があれば「そのバージョンへ上げれば解消する」候補、無ければ修正版が未提供の指摘です。後者は --ignore-unfixed で最初から除けます。
trivy image -f json -o trivy-image.json \
--severity HIGH,CRITICAL --ignore-unfixed myapp:latest--ignore-unfixed は「直しようがない指摘」を隠すだけで、リスクが無くなるわけではありません。Claude Codeに渡す対象を「今すぐ直せるもの」に絞る目的で使い、隠した件数は別途把握しておきます。
IaCの場合は同じ形で trivy config にフォーマットを指定します。
trivy config -f json -o trivy-config.json \
--severity HIGH,CRITICAL ./infra設定ミスの指摘は、表形式の出力だと「HIGH: Specify at least 1 USER command in Dockerfile with non-root user as argument」のように、指摘文、説明、該当ファイルの行範囲(例: deployment.yaml:16-19)が並びます。行範囲が付くので、Claude Codeは該当箇所を直接開いて直せます。
Claude Codeに渡して直させる
ファイルを作ったら、プロンプトで読ませます。ポイントは、指摘をすべて直させるのではなく、直す範囲と禁止事項を先に決めることです。
trivy-image.json を読み、FixedVersion があるものだけ直してください。
- 対象は Dockerfile とロックファイル。アプリのコードは触らない
- FixedVersion が無い指摘は、一覧にして報告するだけにする
- 直したら、修正した CVE の ID とパッケージ名を表にまとめるイメージの脆弱性は、直し方が指摘の種類で分かれます。
- OSパッケージ(
Classがos-pkgs): ベースイメージのタグを更新する。FixedVersionが示すバージョンのパッケージを入れ直す記述を足す方法もある - 言語の依存パッケージ: ロックファイルの該当バージョンを
FixedVersion以上に上げる - Dockerfileの設定ミス:
USERの追加など、指摘文が示す書き換え
Dockerfile側の書き換えは、既存記事のDockerfileの最適化と重なります。IaCの修正は、Terraformならplan差分の検証、Kubernetesならマニフェストの書き方と合わせて確認すると、指摘が消えても意図しない変更が入っていないかを見られます。
再スキャンで閉じる
直したあとは、同じコマンドをもう一度回して指摘が消えたことを確かめます。このとき人の目やClaudeの読み取りに頼らず、終了コードで判定できるようにします。
Trivyは既定では、セキュリティ上の問題が見つかっても終了コード0で終わります。--exit-code を指定すると、問題があるときに非ゼロで終わらせられます。
trivy image --exit-code 1 --severity HIGH,CRITICAL \
--ignore-unfixed myapp:latest
echo "exit=$?"公式の例には、--exit-code 1 --severity CRITICAL のようにCRITICALだけを失敗条件にする使い方や、--exit-code 0 --severity MEDIUM,HIGH で中・高は報告のみにする使い方があります。Claude Codeには「終了コードが0になるまで修正と再スキャンを繰り返す」と頼めますが、回数の上限も決めておきます。
修正後は上のコマンドで再スキャンし、終了コードが 0 になるまで続けてください。
ただし 3 回直しても 0 にならない場合は、残った CVE を一覧にして止めてください。上限が無いと、直らない指摘に対してClaude Codeが無関係なファイルまで書き換え続けることがあります。上限を超えたら人が判断する形にしておくと、差分の見直しも楽です。イメージを再ビルドしてから再スキャンする必要があるので、docker build と trivy image を続けて実行するスクリプトにまとめておくと、手順の抜けを防げます。
誤検知と許容する指摘の扱い
再スキャンでどうしても残る指摘には、次の3通りがあります。
- 実際には影響しない(使っていない機能のCVEなど)
- 影響はあるが、すぐには直せず期限付きで受け入れる
- 修正版がまだ無い
これらは、Claudeに「無視して」と口頭で頼むのではなく、Trivyの無視ファイルに理由付きで記録します。.trivyignore.yaml はYAML形式で、id(必須)、paths、purls、expired_at、statement が書けます。statement は理由を書く欄で、フィルタリングには使われません。
vulnerabilities:
- id: CVE-2023-29491
statement: 使っていないライブラリ経由。差し替えは次のリリースで対応
expired_at: 2026-12-31
misconfigurations:
- id: AVD-DS-0002
paths:
- "docs/Dockerfile"
statement: このイメージはroot権限が必要.trivyignore.yaml は実験的機能のため、--ignorefile でパスを明示します。
trivy image --ignorefile ./.trivyignore.yaml \
--exit-code 1 --severity HIGH,CRITICAL myapp:latestexpired_at を付けておくと、期限を過ぎたあとは再び検出されます。「誰も見ないまま許容が残り続ける」のを防げるので、Claude Codeに無視ファイルを書かせるときは、statement と expired_at を必須にするとよいでしょう。拡張子を持たない簡易版の .trivyignore もあり、CVE-2019-14697 exp:2023-01-01 のように期限を付けられますが、理由欄はコメント行で書く形です。
もう1つの選択肢がVEX(Vulnerability Exploitability Exchange)です。--vex で渡すと、「影響を受けない」と宣言された指摘を結果から外せます。--show-suppressed を付ければ、外された指摘とその理由も一覧で確認できます。VEXはCSAFなどの形式の文書で影響の有無を宣言する仕組みで、社内の許容リストだけなら .trivyignore.yaml で足ります。
無視ファイルの書き換えは、Claude Codeに任せる範囲を決めておきたい操作です。指摘を消すだけなら、スキャン結果は簡単にきれいになってしまいます。レビューでは、無視ファイルの差分が増えていないかを最初に見ます。
Claude Code側の権限とCLAUDE.md
Trivyは初回に脆弱性データベースを取得するため、ネットワークが必要です。ログにも「Updating vulnerability database...」と出ます。ネットワークを制限した環境で回すときは、あらかじめデータベースを用意する運用が要ります。
Claude Codeに毎回許可を聞かれないよう、スキャンのコマンドだけを許可します。ルールは Bash(コマンド *) の形で書き、* はサブコマンドの後に置きます。権限の見方は/permissionsコマンドの記事にまとめています。
{
"permissions": {
"allow": [
"Bash(trivy image *)",
"Bash(trivy fs *)",
"Bash(trivy config *)"
]
}
}あわせて、CLAUDE.md にスキャンの共通ルールを書いておくと、毎回プロンプトに書かずに済みます。
## Trivy スキャン
- 結果は JSON で出力し、HIGH と CRITICAL だけを対象にする
- 修正後は `--exit-code 1` で再スキャンし、0 になるまで最大 3 回
- `.trivyignore.yaml` への追記は、人の承認があるまで行わないCIで同じ流れを回したい場合は、claude -p の非対話モードが使えます。非対話モードの使い方にあるとおり、--allowedTools で使えるツールを絞れます。ただし、CIの判定そのものは trivy --exit-code に任せ、Claude Codeは「落ちた原因を読んで修正案を作る」役にとどめると、判定の再現性が保てます。
他のスキャナーとの使い分け
Trivyは、イメージ・依存関係・IaCを1つのコマンドで扱えるのが特徴です。SBOMを軸に依存パッケージの脆弱性を突き合わせたいならSBOMのOSV-Scanner突合、Snyk製のスキャンをClaude Codeの作業中に呼ばせたいならSnyk Studioの組み込みが別の経路です。Trivyの結果をCSVの是正対応表にして優先度を付ける流れは、脆弱性スキャン結果の是正対応表の手順がそのまま使えます。
よくあるつまずき
- 指摘が減らない: Dockerfileを直しただけでは、スキャン対象のイメージは変わりません。再ビルドしたイメージに対して再スキャンします
- 同じ指摘がまた出る: 無視ファイルの
pathsが実際の対象パスと合っていない可能性があります。公式の例はdocs/Dockerfileのような相対パスで書かれています。JSONのTargetと見比べて揃えます - 終了コードが常に0:
--exit-codeを付け忘れているのが典型です。既定は0です - Claude Codeが修正済みと報告するのに残る: 修正がイメージに反映されていません。報告ではなく、再スキャンの終了コードを根拠にします