Skip to content
Vladimir Chavkov
Go back

Trivy: Complete Container and Infrastructure Security Scanner Guide

Edit page

Trivy: Complete Container and Infrastructure Security Scanner Guide

Trivy is a comprehensive, open-source security scanner by Aqua Security that detects vulnerabilities, misconfigurations, secrets, and licenses in container images, filesystems, git repositories, Kubernetes clusters, and Infrastructure as Code. As the most popular container security scanner in the CNCF ecosystem, Trivy is essential for any DevSecOps pipeline.

What is Trivy?

Trivy is an all-in-one security scanner that covers:

Key Features

  1. Container Image Scanning: Detect OS and language package vulnerabilities
  2. Filesystem Scanning: Scan local project directories
  3. IaC Scanning: Analyze Terraform, CloudFormation, Kubernetes manifests
  4. Kubernetes Scanning: Scan running clusters for misconfigurations
  5. SBOM Generation: Create Software Bill of Materials (CycloneDX, SPDX)
  6. Secret Detection: Find leaked credentials and API keys
  7. License Scanning: Identify package license compliance issues

Trivy vs. Other Security Scanners

FeatureTrivyGrypeSnykClairDocker Scout
CostFree/OSSFree/OSSFreemiumFree/OSSFreemium
Container ImagesYesYesYesYesYes
FilesystemYesYesYesNoNo
IaC ScanningYesNoYesNoNo
K8s Cluster ScanYesNoYesNoNo
Secret DetectionYesNoYesNoNo
SBOMYesYesYesNoYes
License ScanningYesNoYesNoYes
CI/CD IntegrationExcellentGoodExcellentLimitedDocker only
Offline ModeYesYesNoNoNo
SpeedFastFastModerateSlowFast
LicenseApache 2.0Apache 2.0ProprietaryApache 2.0Proprietary

Installation

Terminal window
# macOS
brew install trivy
# Linux (Debian/Ubuntu)
sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update && sudo apt-get install trivy
# Docker
docker run --rm aquasec/trivy:latest image alpine:3.19
# Helm (Trivy Operator for Kubernetes)
helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm install trivy-operator aqua/trivy-operator \
--namespace trivy-system --create-namespace

Container Image Scanning

Terminal window
# Scan a container image
trivy image nginx:1.25
# Scan with severity filter
trivy image --severity HIGH,CRITICAL nginx:1.25
# Scan and fail on critical vulnerabilities
trivy image --exit-code 1 --severity CRITICAL nginx:1.25
# Scan a local Docker image
trivy image --input myapp.tar
# Scan with JSON output
trivy image --format json --output results.json nginx:1.25
# Scan ignoring unfixed vulnerabilities
trivy image --ignore-unfixed nginx:1.25
# Scan specific types only (os, library)
trivy image --vuln-type os nginx:1.25
trivy image --vuln-type library node:20

Sample Output

nginx:1.25 (debian 12.4)
=========================
Total: 42 (HIGH: 8, CRITICAL: 2)
┌──────────────────┬────────────────┬──────────┬────────────┬───────────────┬──────────────────────────────┐
│ Library │ Vulnerability │ Severity │ Installed │ Fixed Version │ Title │
├──────────────────┼────────────────┼──────────┼────────────┼───────────────┼──────────────────────────────┤
│ libssl3 │ CVE-2024-0727 │ CRITICAL │ 3.0.11-1 │ 3.0.13-1 │ OpenSSL: denial of service │
│ curl │ CVE-2023-46218 │ HIGH │ 7.88.1-10 │ 7.88.1-10+d12 │ curl: cookie injection │
└──────────────────┴────────────────┴──────────┴────────────┴───────────────┴──────────────────────────────┘

Filesystem and Repository Scanning

Terminal window
# Scan current directory
trivy fs .
# Scan a specific path
trivy fs /path/to/project
# Scan a git repository
trivy repo https://github.com/org/project
# Scan for secrets
trivy fs --scanners secret .
# Scan for licenses
trivy fs --scanners license .
# Scan for vulnerabilities and secrets
trivy fs --scanners vuln,secret .

Infrastructure as Code Scanning

Terminal window
# Scan Terraform files
trivy config ./terraform/
# Scan Kubernetes manifests
trivy config ./k8s/
# Scan Dockerfiles
trivy config --file-patterns "Dockerfile" .
# Scan Helm charts
trivy config ./charts/myapp/
# Scan with specific severity
trivy config --severity HIGH,CRITICAL ./terraform/
# Custom policy scanning
trivy config --policy ./custom-policies/ ./terraform/

Sample IaC Finding

Dockerfile (dockerfile)
========================
Tests: 23 (SUCCESSES: 20, FAILURES: 3)
Failures: 3 (HIGH: 2, CRITICAL: 1)
CRITICAL: Specify a tag in the 'FROM' statement for image 'node'
═══════════════════════════════════════════════════════════════════
Using the latest tag can lead to unpredictable builds.
HIGH: 'RUN' instruction using 'sudo'
═══════════════════════════════════════
Avoid using 'sudo' as it can lead to unpredictable behavior.

Kubernetes Cluster Scanning

Terminal window
# Scan the entire cluster
trivy k8s --report summary cluster
# Scan specific namespace
trivy k8s --namespace production --report all
# Scan for vulnerabilities in running images
trivy k8s --scanners vuln cluster
# Scan for misconfigurations
trivy k8s --scanners misconfig cluster
# Scan specific workload
trivy k8s --namespace production deployment/myapp
# Generate compliance report (NSA, CIS)
trivy k8s --compliance k8s-nsa cluster
trivy k8s --compliance k8s-cis cluster

Trivy Operator (Continuous Scanning)

trivy-operator-values.yaml
trivy:
ignoreUnfixed: true
severity: HIGH,CRITICAL
timeout: 10m0s
operator:
scanJobTolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
vulnerabilityScannerEnabled: true
configAuditScannerEnabled: true
exposedSecretScannerEnabled: true
scanJobsConcurrentLimit: 10
scanJobsRetryDelay: 30s
compliance:
cron: "0 */6 * * *"
reportType:
- k8s-nsa
- k8s-cis
Terminal window
# Check vulnerability reports
kubectl get vulnerabilityreports -A
# Check config audit reports
kubectl get configauditreports -A
# Check exposed secret reports
kubectl get exposedsecretreports -A
# Detailed report for a specific workload
kubectl get vulnerabilityreport -n production \
-l trivy-operator.resource.name=myapp -o yaml

SBOM Generation

Terminal window
# Generate CycloneDX SBOM
trivy image --format cyclonedx --output sbom.json nginx:1.25
# Generate SPDX SBOM
trivy image --format spdx-json --output sbom-spdx.json nginx:1.25
# Scan an existing SBOM
trivy sbom sbom.json
# Generate SBOM for filesystem
trivy fs --format cyclonedx --output fs-sbom.json .

CI/CD Integration

GitHub Actions

.github/workflows/security-scan.yml
name: Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
trivy-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
format: sarif
output: trivy-results.sarif
severity: HIGH,CRITICAL
exit-code: 1
- name: Upload scan results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: trivy-results.sarif
- name: Trivy IaC scan
uses: aquasecurity/trivy-action@master
with:
scan-type: config
scan-ref: .
severity: HIGH,CRITICAL
exit-code: 1
- name: Trivy filesystem scan
uses: aquasecurity/trivy-action@master
with:
scan-type: fs
scan-ref: .
scanners: vuln,secret
severity: HIGH,CRITICAL

GitLab CI

.gitlab-ci.yml
trivy-scan:
stage: security
image:
name: aquasec/trivy:latest
entrypoint: [""]
script:
- trivy image --exit-code 1 --severity HIGH,CRITICAL
--format json --output gl-container-scanning-report.json
$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- trivy fs --exit-code 1 --severity HIGH,CRITICAL
--scanners vuln,secret .
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
allow_failure: false

Configuration

trivy.yaml

# trivy.yaml (project root)
severity:
- HIGH
- CRITICAL
vulnerability:
type:
- os
- library
ignore-unfixed: true
misconfiguration:
severity:
- HIGH
- CRITICAL
secret:
config: trivy-secret.yaml
scan:
skip-dirs:
- node_modules
- vendor
- .git
skip-files:
- "**/*_test.go"
db:
skip-update: false
download-only: false
cache:
dir: /tmp/trivy-cache

Ignore File

.trivyignore.yaml
vulnerabilities:
- id: CVE-2023-12345
statement: "Not exploitable in our context"
expires: 2026-06-01
- id: CVE-2023-67890
paths:
- "usr/lib/libfoo.so"
statement: "Mitigated by WAF"
misconfigurations:
- id: DS002
statement: "healthcheck handled by Kubernetes"
paths:
- "Dockerfile"

Production Best Practices

Checklist


Secure Your Container Pipeline

Building a comprehensive container security strategy requires expertise in vulnerability management, IaC scanning, and compliance. At chavkov.com, I deliver hands-on security training that equips your team with production-ready DevSecOps skills.

Contact me to discuss security training options for your team.


Edit page
Share this post on:

Previous Post
Microservices Architecture: Best Practices and Design Patterns
Next Post
Harbor: Enterprise Container Registry Complete Guide