Trivy - Container Vulnerability Scanner
Scan Docker images, filesystems, and IaC configs for vulnerabilities and misconfigurations with Trivy.
Trivy is an open-source vulnerability scanner by Aqua Security. It scans Docker images, filesystems, Git repositories, Kubernetes manifests, and Terraform configs for CVEs, misconfigurations, and secrets.
Install Trivy
Debian/Ubuntu via apt:
curl -fsSL https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor -o /usr/share/keyrings/trivy.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" \
| tee /etc/apt/sources.list.d/trivy.list
apt-get update && apt-get install -y trivyBinary (any Linux):
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
trivy --versionScan a Docker Image
# Scan a public image
trivy image nginx:latest
# Scan only HIGH and CRITICAL severities
trivy image --severity HIGH,CRITICAL nginx:latest
# Scan a specific image from a private registry
docker pull registry.example.com/myapp:1.0
trivy image registry.example.com/myapp:1.0Output shows: library name, vulnerability ID, severity, installed version, fixed version.
Skip Unfixed Vulnerabilities
Many CVEs have no fix yet. Use --ignore-unfixed to focus only on vulnerabilities that have a patched version available.
trivy image --ignore-unfixed --severity HIGH,CRITICAL nginx:latestScan a Local Filesystem
Useful for scanning application code and dependencies:
trivy fs /var/www/myapp
# Scan current directory
trivy fs .This detects vulnerabilities in language package files (package-lock.json, composer.lock, requirements.txt, go.sum, etc.).
Scan a Git Repository
trivy repo https://github.com/myorg/myapp
# Local repo
trivy repo /home/user/myprojectScan IaC Configurations
Trivy can detect misconfigurations in Dockerfiles, Kubernetes YAML, Terraform, and more:
# Scan all IaC files in current directory
trivy config .
# Scan a specific Dockerfile
trivy config Dockerfile
# Scan Kubernetes manifests
trivy config k8s/Example findings: containers running as root, missing resource limits, privileged containers.
Output Formats
# JSON output (for scripting/CI)
trivy image --format json --output results.json nginx:latest
# SARIF (for GitHub Security tab)
trivy image --format sarif --output results.sarif nginx:latest
# Table (default, human-readable)
trivy image --format table nginx:latest
# CycloneDX SBOM
trivy image --format cyclonedx --output sbom.json nginx:latestGenerate SBOM (Software Bill of Materials)
trivy sbom --artifact-type image nginx:latestUpdate Vulnerability Database
Trivy downloads its DB on first run and caches it. Update manually:
trivy image --download-db-onlyThe cache is stored in ~/.cache/trivy/ by default.
CI/CD Integration
GitHub Actions
name: Trivy scan
on: [push]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan image
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
format: table
exit-code: 1
severity: CRITICAL,HIGH
ignore-unfixed: trueShell script (exit 1 on CRITICAL)
trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed myapp:latest
if [ $? -ne 0 ]; then
echo "Critical vulnerabilities found, blocking deployment"
exit 1
fiScan a Running Container
# Export container filesystem and scan
docker export $(docker ps -q -f name=myapp) | trivy rootfs --input -Ignore Specific CVEs
Create a .trivyignore file in the project root:
# .trivyignore
CVE-2023-1234 # false positive, not exploitable in our config
CVE-2022-5678 # accepted risk, no fix availableScan Kubernetes Cluster
# Install trivy-operator or use CLI
trivy k8s --report summary cluster
trivy k8s --namespace production allTrivy pulls vulnerability data from public databases (NVD, GitHub Advisory, etc.). In air-gapped environments, use --skip-db-update with a pre-downloaded DB or mirror the DB internally.
Useful Flags Reference
| Flag | Description |
|---|---|
--severity | Filter by severity: UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL |
--ignore-unfixed | Skip CVEs with no fix available |
--exit-code 1 | Return non-zero exit code if vulnerabilities found |
--format | Output format: table, json, sarif, cyclonedx, spdx |
--skip-db-update | Use cached DB, no network required |
--quiet | Suppress progress output |
--timeout | Scan timeout (default 5m0s) |