Security

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 trivy

Binary (any Linux):

curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
trivy --version

Scan 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.0

Output 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:latest

Scan 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/myproject

Scan 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:latest

Generate SBOM (Software Bill of Materials)

trivy sbom --artifact-type image nginx:latest

Update Vulnerability Database

Trivy downloads its DB on first run and caches it. Update manually:

trivy image --download-db-only

The 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: true

Shell 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
fi

Scan 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 available

Scan Kubernetes Cluster

# Install trivy-operator or use CLI
trivy k8s --report summary cluster
trivy k8s --namespace production all

Trivy 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

FlagDescription
--severityFilter by severity: UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL
--ignore-unfixedSkip CVEs with no fix available
--exit-code 1Return non-zero exit code if vulnerabilities found
--formatOutput format: table, json, sarif, cyclonedx, spdx
--skip-db-updateUse cached DB, no network required
--quietSuppress progress output
--timeoutScan timeout (default 5m0s)

On this page