Security Tools

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.

March 9, 20266 min readShipSafer Team

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 keys
  • config — 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.

Check Your Security Score — Free

See exactly how your domain scores on DMARC, TLS, HTTP headers, and 25+ other automated security checks in under 60 seconds.