Aqua Trivy - Comprehensive Security Scanner
When to Use Trivy
Ideal scenarios:
- Container image vulnerability scanning
- Filesystem and repository scanning
- Infrastructure-as-Code (IaC) misconfiguration detection
- Secrets detection in code and images
- Software Bill of Materials (SBOM) generation
- License compliance checking
- Kubernetes cluster security assessment
- CI/CD security gates
Complements other tools:
- Use alongside Semgrep/CodeQL for application code analysis
- Combine with KICS for additional IaC coverage
- Use with Gitleaks for dedicated secrets scanning
- Pair with OSV-Scanner/Depscan for enhanced SCA
When NOT to Use
Do NOT use this skill for:
- Deep application code vulnerability analysis (use Semgrep or CodeQL)
- API endpoint discovery (use Noir)
- Advanced SAST with taint tracking (use CodeQL)
- Penetration testing (use specialized tools)
Installation
Homebrew (Recommended for macOS/Linux)
# macOS and Linux (preferred method)
brew install trivy
# Verify installation
trivy --version
Other Installation Methods
# Docker
docker pull aquasec/trivy:latest
# Install script (Linux/macOS)
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# apt (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 -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy
# yum/dnf (RHEL/CentOS/Fedora)
sudo rpm -ivh https://github.com/aquasecurity/trivy/releases/latest/download/trivy_*_Linux-64bit.rpm
# Windows (Chocolatey)
choco install trivy
# Windows (Scoop)
scoop install trivy
# Go install
go install github.com/aquasecurity/trivy/cmd/trivy@latest
Core Workflow
1. Quick Scan
# Scan container image
trivy image nginx:latest
# Scan filesystem/project directory
trivy fs /path/to/project
# Scan current directory
trivy fs .
# Scan remote git repository
trivy repo https://github.com/owner/repo
# Scan Kubernetes cluster
trivy k8s --report summary cluster
2. SARIF Output
# Container image to SARIF
trivy image --format sarif --output results.sarif nginx:latest
# Filesystem to SARIF
trivy fs --format sarif --output results.sarif /path/to/project
# Repository to SARIF
trivy repo --format sarif --output results.sarif https://github.com/owner/repo
# IaC scan to SARIF
trivy config --format sarif --output iac-results.sarif /path/to/terraform
3. Specific Scanner Types
# Vulnerability scanning only
trivy image --scanners vuln nginx:latest
# Secrets scanning only
trivy fs --scanners secret /path/to/project
# Misconfiguration scanning only
trivy config /path/to/iac
# License scanning
trivy image --scanners license nginx:latest
# Combined scanners
trivy fs --scanners vuln,secret,misconfig /path/to/project
4. SBOM Generation
# Generate CycloneDX SBOM
trivy image --format cyclonedx --output sbom.json nginx:latest
# Generate SPDX SBOM
trivy image --format spdx-json --output sbom.spdx.json nginx:latest
# Scan existing SBOM for vulnerabilities
trivy sbom sbom.json
Scan Targets
| Target | Command | Description |
|---|---|---|
| Container Image | trivy image IMAGE | Scan container images from registries or local |
| Filesystem | trivy fs PATH | Scan local project directory |
| Repository | trivy repo URL | Scan remote git repository |
| Kubernetes | trivy k8s | Scan Kubernetes cluster resources |
| IaC/Config | trivy config PATH | Scan IaC files (Terraform, CloudFormation, etc.) |
| SBOM | trivy sbom FILE | Scan existing SBOM file |
| VM Image | trivy vm IMAGE | Scan virtual machine images |
| Rootfs | trivy rootfs PATH | Scan root filesystem |
Supported Ecosystems
Package Managers
| Ecosystem | Manifest/Lock Files |
|---|---|
| npm | package.json, package-lock.json, yarn.lock, pnpm-lock.yaml |
| Python | requirements.txt, Pipfile.lock, poetry.lock, setup.py |
| Go | go.mod, go.sum |
| Rust | Cargo.lock |
| Java | pom.xml, build.gradle, gradle.lockfile |
| Ruby | Gemfile.lock |
| PHP | composer.lock |
| .NET | packages.lock.json, *.deps.json |
| Swift | Package.resolved |
| Dart | pubspec.lock |
| Elixir | mix.lock |
| Conan (C/C++) | conan.lock |
IaC Platforms
| Platform | File Types |
|---|---|
| Terraform | *.tf, *.tf.json |
| CloudFormation | *.yaml, *.json (CFN templates) |
| Kubernetes | *.yaml (K8s manifests) |
| Helm | Chart.yaml, values.yaml |
| Docker | Dockerfile |
| Azure ARM | *.json (ARM templates) |
Output Formats
# Table format (default, human-readable)
trivy image nginx:latest
# JSON output
trivy image --format json --output results.json nginx:latest
# SARIF output (for CI/CD integration)
trivy image --format sarif --output results.sarif nginx:latest
# CycloneDX SBOM
trivy image --format cyclonedx --output sbom.cdx.json nginx:latest
# SPDX SBOM
trivy image --format spdx-json --output sbom.spdx.json nginx:latest
# GitHub dependency snapshot
trivy image --format github nginx:latest
# Template output (custom)
trivy image --format template --template "@contrib/html.tpl" --output report.html nginx:latest
Advanced Options
Severity Filtering
# Critical and High only
trivy image --severity CRITICAL,HIGH nginx:latest
# All severities (default)
trivy image --severity UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL nginx:latest
# Exit with error on findings
trivy image --exit-code 1 --severity HIGH,CRITICAL nginx:latest
Vulnerability Options
# Show only fixed vulnerabilities
trivy image --ignore-unfixed nginx:latest
# Ignore specific vulnerabilities
trivy image --ignorefile .trivyignore nginx:latest
# Skip vulnerability database update
trivy image --skip-db-update nginx:latest
# Offline mode (use cached DB)
trivy image --offline-scan nginx:latest
Image Scanning Options
# Scan from tar archive
trivy image --input image.tar
# Scan specific platform
trivy image --platform linux/amd64 nginx:latest
# Scan with image config
trivy image --image-config-scanners config nginx:latest
# Skip files by pattern
trivy image --skip-files "/path/to/skip" nginx:latest
# Skip directories
trivy image --skip-dirs node_modules nginx:latest
Secret Scanning
# Enable secret scanning
trivy fs --scanners secret /path/to/project
# Custom secret config
trivy fs --scanners secret --secret-config trivy-secret.yaml /path/to/project
CI/CD Integration (GitHub Actions)
name: Trivy Security Scan
on:
push:
branches: [main]
pull_request:
schedule:
- cron: '0 0 * * *' # Daily
jobs:
trivy-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner (filesystem)
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-fs-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Upload Trivy SARIF (filesystem)
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-fs-results.sarif'
category: trivy-fs
- name: Run Trivy config scanner (IaC)
uses: aquasecurity/trivy-action@master
with:
scan-type: 'config'
scan-ref: '.'
format: 'sarif'
output: 'trivy-config-results.sarif'
- name: Upload Trivy SARIF (config)
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-config-results.sarif'
category: trivy-config
container-scan:
runs-on: ubuntu-latest
needs: [build] # Assuming a build job creates the image
steps:
- name: Run Trivy container scan
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-image-results.sarif'
severity: 'CRITICAL,HIGH'
ignore-unfixed: true
- name: Upload Trivy SARIF (image)
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-image-results.sarif'
category: trivy-image
Configuration
Config File (trivy.yaml)
# trivy.yaml
severity:
- CRITICAL
- HIGH
- MEDIUM
exit-code: 1
ignore-unfixed: true
# Vulnerability settings
vulnerability:
type:
- os
- library
# Secret scanning
secret:
config: trivy-secret.yaml
# Misconfiguration settings
misconfiguration:
terraform:
excluded-checks:
- AVD-AWS-0013
# Skip patterns
skip-files:
- "**/*.test.js"
- "**/testdata/**"
skip-dirs:
- node_modules
- .git
- vendor
# Cache settings
cache:
dir: /tmp/trivy-cache
Ignore File (.trivyignore)
# .trivyignore
# Ignore specific CVEs
CVE-2023-12345
CVE-2023-67890
# Ignore with expiration
CVE-2024-11111 exp:2025-06-01
# Ignore specific package vulnerabilities
CVE-2024-22222 pkg:lodash
# Secret ignore patterns
aws-access-key-id
Secret Config (trivy-secret.yaml)
# trivy-secret.yaml
rules:
- id: custom-api-key
category: general
title: Custom API Key
severity: HIGH
regex: 'CUSTOM_API_KEY[=:]\s*["\']?([A-Za-z0-9]{32})["\']?'
allow-rules:
- id: allow-test-secrets
description: Allow test/mock secrets
path: '.*test.*|.*mock.*'
Common Use Cases
1. Container Security Pipeline
# Build image
docker build -t myapp:latest .
# Scan for vulnerabilities
trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:latest
# Generate SBOM
trivy image --format cyclonedx --output sbom.json myapp:latest
# Export SARIF for tracking
trivy image --format sarif --output results.sarif myapp:latest
2. IaC Security Review
# Scan Terraform files
trivy config --format sarif --output iac-results.sarif ./terraform
# Scan Kubernetes manifests
trivy config --format sarif --output k8s-results.sarif ./k8s
# Scan Dockerfiles
trivy config --format sarif --output docker-results.sarif .
3. Repository Security Audit
# Full repository scan
trivy fs --scanners vuln,secret,misconfig \
--format sarif --output full-scan.sarif \
/path/to/project
# Scan remote repository
trivy repo --format sarif --output repo-scan.sarif \
https://github.com/owner/repo
4. Kubernetes Cluster Assessment
# Summary report
trivy k8s --report summary cluster
# Detailed scan with SARIF
trivy k8s --format sarif --output k8s-cluster.sarif cluster
# Scan specific namespace
trivy k8s --namespace production --report all cluster
5. Supply Chain Security
# Generate SBOM
trivy image --format cyclonedx --output sbom.cdx.json myapp:latest
# Scan SBOM for vulnerabilities
trivy sbom sbom.cdx.json
# Sign SBOM with cosign (if available)
cosign sign-blob --key cosign.key sbom.cdx.json
Understanding Output
SARIF Structure
Trivy SARIF v2.1.0 includes:
- Rules: Each vulnerability, misconfiguration, or secret type
- Results: Individual findings with location
- Properties:
- CVE/vulnerability ID
- Severity (CRITICAL, HIGH, MEDIUM, LOW, UNKNOWN)
- CVSS scores
- Package name and version
- Fixed version (if available)
- References and links
- File path and line number (for secrets/misconfig)
Vulnerability Information
Each finding includes:
- VulnerabilityID: CVE-YYYY-NNNNN
- PkgName: Affected package name
- InstalledVersion: Current vulnerable version
- FixedVersion: Version with fix (if available)
- Severity: CRITICAL, HIGH, MEDIUM, LOW, UNKNOWN
- Title: Brief vulnerability description
- Description: Detailed explanation
- References: Links to advisories
- CVSS: Score vectors if available
Remediation Workflow
Step 1: Scan
trivy image --format json --output vulns.json myapp:latest
Step 2: Prioritize
# Extract critical vulnerabilities
jq '.Results[].Vulnerabilities[] | select(.Severity == "CRITICAL")' vulns.json
# Count by severity
jq '[.Results[].Vulnerabilities[].Severity] | group_by(.) | map({severity: .[0], count: length})' vulns.json
Step 3: Fix
# Review fix versions
jq -r '.Results[].Vulnerabilities[] | select(.FixedVersion != null) | "\(.PkgName): \(.InstalledVersion) -> \(.FixedVersion)"' vulns.json
# Update base image
# Edit Dockerfile: FROM nginx:1.25-alpine (newer patched version)
# Rebuild
docker build -t myapp:latest .
Step 4: Verify
# Rescan
trivy image --format json --output post-fix.json myapp:latest
# Compare vulnerability counts
echo "Before: $(jq '[.Results[].Vulnerabilities[]] | length' vulns.json)"
echo "After: $(jq '[.Results[].Vulnerabilities[]] | length' post-fix.json)"
Performance Optimization
# Skip database update (use cached)
trivy image --skip-db-update nginx:latest
# Offline scanning
trivy image --offline-scan nginx:latest
# Skip specific directories
trivy fs --skip-dirs node_modules,.git,vendor /path/to/project
# Cache directory (faster subsequent scans)
trivy image --cache-dir /tmp/trivy-cache nginx:latest
# Parallel scanning (default)
trivy image --parallel 4 nginx:latest
Database Management
# Download/update vulnerability database
trivy image --download-db-only
# Clear cache
trivy clean --all
# Check database status
trivy version --format json | jq '.VulnerabilityDB'
Limitations
- Image layers: Only scans final image filesystem, not intermediate layers
- Runtime: Static analysis only; doesn't detect runtime vulnerabilities
- Custom packages: May not detect vulnerabilities in custom/private packages
- False positives: OS package detection may include packages not actually installed
- Zero-days: Only detects publicly disclosed vulnerabilities
Rationalizations to Reject
| Shortcut | Why It's Wrong |
|---|---|
| "Base image from vendor is secure" | Vendors lag on patches; always scan regardless of source |
| "Only scan production images" | Dev/staging images can leak secrets or introduce supply chain attacks |
| "Skip IaC scanning for speed" | Misconfigurations are easier to fix before deployment |
| "Ignore unfixed vulnerabilities" | Even without patches, you can mitigate or compensate with other controls |
| "Weekly scans are enough" | New CVEs are disclosed daily; scan on every build and daily on deployed images |
| "Low severity = safe to ignore" | Low severity issues can combine into exploitable chains |
References
- Repository: https://github.com/aquasecurity/trivy
- Documentation: https://trivy.dev/
- GitHub Action: https://github.com/aquasecurity/trivy-action
- Trivy Operator (Kubernetes): https://github.com/aquasecurity/trivy-operator
- VS Code Extension: https://marketplace.visualstudio.com/items?itemName=AquaSecurityOfficial.trivy-vulnerability-scanner
- Vulnerability Database: https://github.com/aquasecurity/trivy-db
- SARIF Spec: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html