Container images bundle an operating system and libraries, and those contain known vulnerabilities (CVEs) that get discovered over time. Trivy is a popular open-source scanner that checks images, filesystems, Git repositories and configuration files for vulnerabilities, leaked secrets and misconfigurations. It can also generate a Software Bill of Materials (SBOM): the list of everything inside your image.

Install

# Debian/Ubuntu (official repository)
sudo apt-get install -y wget gnupg
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 generic main" | sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update && sudo apt-get install -y trivy

# or run it as a container
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image nginx:1.27

Scan an image

trivy image nginx:1.27
trivy image --severity HIGH,CRITICAL myapp:1.8.3
trivy image --ignore-unfixed --severity HIGH,CRITICAL myapp:1.8.3

The report lists each vulnerable package, the CVE, the severity, the installed version, and the fixed version (if one exists). --ignore-unfixed hides vulnerabilities without an available fix, so you can focus on what you can act on.

The first run downloads the vulnerability database. Later runs update it automatically.

Scan for secrets and misconfigurations

trivy image --scanners vuln,secret myapp:1.8.3          # also look for embedded keys/tokens
trivy fs --scanners vuln,secret,misconfig .             # a project directory (lockfiles, Dockerfile)
trivy config .                                          # Dockerfile, Compose, Kubernetes, Terraform

Misconfiguration checks catch things like containers running as root, missing resource limits, or privileged: true. See Docker secrets and Docker security best practices.

Generate an SBOM

An SBOM lists every package and version in an image, which is useful for audits, licence checks, and quickly answering “are we affected by CVE-X?”:

trivy image --format cyclonedx --output sbom.json myapp:1.8.3
trivy image --format spdx-json --output sbom.spdx.json myapp:1.8.3
trivy sbom sbom.json          # scan an existing SBOM later, against the latest vulnerability data

Use it in CI

Fail the build when serious, fixable issues appear:

trivy image --exit-code 1 --ignore-unfixed --severity CRITICAL,HIGH registry.example.com/myapp:${GIT_SHA}

GitHub Actions has an official aquasecurity/trivy-action. Run scans on every build, and on a schedule (weekly), because new CVEs are published for images that haven’t changed. See CI/CD pipeline explained.

Handling results

  1. Rebuild with an updated base image. This fixes most OS-package CVEs. See Docker image tags best practices.
  2. Update application dependencies (lockfiles) for language-package CVEs.
  3. Reduce the attack surface: slim or distroless bases, multi-stage builds. See Alpine vs Debian base images.
  4. Accept or ignore findings that don’t apply (for example, a vulnerable function your app never uses), with a documented .trivyignore entry and a review date.

Not every CVE is exploitable in your context. Prioritise critical and high severity, network-reachable components, and anything with a known exploit.

Other tools

Grype + Syft (Anchore), Docker Scout, and registry-integrated scanning (Harbor uses Trivy) do similar jobs. See Harbor.

Quick reference

Task Command
Scan image trivy image <image>
Only actionable high/critical --ignore-unfixed --severity HIGH,CRITICAL
Secrets too --scanners vuln,secret
Config files trivy config .
SBOM trivy image --format cyclonedx -o sbom.json <image>
Fail CI --exit-code 1

Related: Docker private registry and Kubernetes security basics.

  • Docker
  • Security
  • DevOps