Trivy Container Scanning: Complete Guide for DevSecOps Teams
How to install Trivy, scan container images, filesystems, and Git repos, integrate into CI/CD pipelines, and generate SBOMs for your DevSecOps workflow.
Trivy Container Scanning: Complete Guide for DevSecOps Teams
Trivy, built by Aqua Security, has become the default open-source scanner for container images in DevSecOps pipelines. It detects OS package vulnerabilities, application dependency CVEs, misconfigurations, exposed secrets, and generates SBOMs — all from a single binary with no daemon required. This guide covers installation, core scanning workflows, CI integration, and SBOM generation.
Installation
Trivy ships as a single static binary and is available through most package managers.
macOS:
brew install aquasecurity/trivy/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 | sudo apt-key add -
echo "deb 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
Docker (no install required):
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
-v $HOME/.cache/trivy:/root/.cache/trivy \
aquasec/trivy image nginx:latest
Verify installation:
trivy --version
Scanning Container Images
The most common use case is scanning a Docker image before pushing it to a registry.
Scan a public image:
trivy image nginx:1.25
Trivy downloads its vulnerability database on first run (cached in ~/.cache/trivy). The output lists:
- Library — the affected package
- Vulnerability ID — CVE identifier
- Severity — CRITICAL, HIGH, MEDIUM, LOW, UNKNOWN
- Installed Version / Fixed Version — current vs. patched version
- Title — brief description
Scan a local image (built but not pushed):
docker build -t myapp:latest .
trivy image myapp:latest
Filter by severity to reduce noise:
trivy image --severity HIGH,CRITICAL myapp:latest
Exit with non-zero code if vulnerabilities found (for CI gates):
trivy image --exit-code 1 --severity CRITICAL myapp:latest
Ignore unfixed vulnerabilities — useful when no patch is available yet:
trivy image --ignore-unfixed --severity HIGH,CRITICAL myapp:latest
Output formats. Trivy supports table (default), json, sarif, cyclonedx, spdx, and template formats:
trivy image --format json --output results.json myapp:latest
trivy image --format sarif --output trivy-results.sarif myapp:latest
SARIF output integrates directly with GitHub Advanced Security's code scanning interface.
Scanning Filesystems and Source Repositories
Trivy scans are not limited to container images. It can analyze any directory or Git repository for vulnerabilities in application dependencies and misconfigurations.
Scan a local directory:
trivy fs --scanners vuln,secret,config /path/to/project
The --scanners flag controls what Trivy checks:
vuln— package vulnerabilities (package.json, requirements.txt, go.sum, Gemfile.lock, etc.)secret— exposed credentials and API keysconfig— IaC misconfigurations (Dockerfile, Kubernetes YAML, Terraform, CloudFormation)license— open source license compliance
Scan a remote Git repository:
trivy repo https://github.com/your-org/your-repo
This clones the repo, scans all dependency files and IaC, and outputs results. Useful for scanning third-party repositories before integrating them.
Scan a Dockerfile specifically:
trivy config --severity HIGH,CRITICAL Dockerfile
Common Dockerfile findings include running as root, using ADD instead of COPY, pinning to :latest tags, and exposing unnecessary ports.
Secret Scanning
Trivy's secret scanner checks for hardcoded credentials, API keys, tokens, and private keys embedded in source files and container image layers.
trivy image --scanners secret myapp:latest
trivy fs --scanners secret /path/to/repo
Trivy uses pattern matching for common secret types including AWS access keys, GitHub tokens, Stripe keys, private certificates, and generic high-entropy strings. Results include the file path, line number, and a severity rating.
To add custom patterns, create a trivy-secret.yaml config file:
rules:
- id: custom-internal-token
category: general
title: "Internal API Token"
severity: HIGH
regex: "INT-[A-Z0-9]{32}"
path: ".*\\.go$"
Kubernetes Cluster Scanning
Trivy can scan a live Kubernetes cluster for misconfigured workloads, RBAC issues, and vulnerable images running in pods.
trivy k8s --report all cluster
For scanning a single namespace:
trivy k8s --namespace production --report summary cluster
For scanning a specific resource:
trivy k8s deployment/my-api
Results include image vulnerabilities for all running containers plus Kubernetes-specific checks: privileged containers, containers running as root, missing resource limits, and weak network policies.
CI/CD Integration
GitHub Actions
name: Trivy Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
trivy-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t ${{ github.repository }}:${{ github.sha }} .
- name: Run Trivy image scan
uses: aquasecurity/trivy-action@master
with:
image-ref: "${{ github.repository }}:${{ github.sha }}"
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH"
ignore-unfixed: true
exit-code: "1"
- name: Upload Trivy SARIF results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: "trivy-results.sarif"
The if: always() on the upload step ensures results are uploaded even when the scan fails the build, so findings are visible in the GitHub Security tab.
GitLab CI
trivy-scan:
image: aquasec/trivy:latest
script:
- trivy image --exit-code 1 --severity CRITICAL,HIGH
--ignore-unfixed --format sarif
--output trivy.sarif
$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
artifacts:
reports:
sast: trivy.sarif
when: always
SBOM Generation
A Software Bill of Materials (SBOM) is a machine-readable inventory of every component in your software. Trivy generates SBOMs in CycloneDX and SPDX formats.
Generate a CycloneDX SBOM from an image:
trivy image --format cyclonedx --output sbom.cdx.json myapp:latest
Generate an SPDX SBOM:
trivy image --format spdx-json --output sbom.spdx.json myapp:latest
Generate an SBOM from a filesystem:
trivy fs --format cyclonedx --output sbom.cdx.json /path/to/project
SBOMs can be stored in artifact registries alongside images, submitted to customers as part of security documentation, or fed into vulnerability management platforms for continuous monitoring.
Caching and Performance
Trivy's vulnerability database is downloaded once and cached. For CI environments, cache the Trivy DB between runs to avoid repeated downloads:
# GitHub Actions cache
- name: Cache Trivy DB
uses: actions/cache@v4
with:
path: ~/.cache/trivy
key: trivy-db-${{ github.run_id }}
restore-keys: trivy-db-
- name: Update Trivy DB
run: trivy image --download-db-only
For air-gapped environments, download the database on a connected machine and transfer it:
trivy image --download-db-only
tar -czf trivy-db.tar.gz ~/.cache/trivy
# Transfer and extract on air-gapped machine
Ignoring Known False Positives
Create a .trivyignore file at the project root to suppress specific findings:
# Suppress by CVE ID
CVE-2021-44228
# Suppress by CVE ID with comment
CVE-2022-1234 # Mitigated by WAF, not reachable in this context
# Suppress by package name
golang.org/x/text
For more structured suppression with expiry dates and justifications, use VEX (Vulnerability Exploitability eXchange) documents, which Trivy supports as of v0.49.