Ravindra BagaleCourses & study guides Track your progress

Guides

How to Scan Docker Images for Vulnerabilities with Trivy (and Amazon ECR)

To scan a Docker image for vulnerabilities, install Trivy (free, from Aqua Security) and run trivy image <image>. It lists the packages inside the image and matches them with known CVEs, then prints a table by severity. Use --severity HIGH,CRITICAL --ignore-unfixed to see what you can fix today, and --exit-code 1 to fail a CI build. On AWS, also turn on Amazon ECR scan on push.

Quick answer

trivy image nginx:1.27                                   # full report
trivy image --severity HIGH,CRITICAL --ignore-unfixed nginx:1.27
trivy image --exit-code 1 --severity CRITICAL myapp:2.4.1   # CI gate
trivy fs --scanners secret,misconfig .                   # repo: secrets + Dockerfile

A live example first

We compare two versions of the official nginx image on an Ubuntu EC2 instance. First install Trivy (one of the methods from the Trivy documentation):

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy:latest image --severity HIGH,CRITICAL nginx:1.21

Trimmed output:

nginx:1.21 (debian 11.6)
Total: 120 (HIGH: 98, CRITICAL: 22)

┌──────────────┬────────────────┬──────────┬───────────────────┬───────────────┐
│   Library    │ Vulnerability  │ Severity │ Installed Version │ Fixed Version │
├──────────────┼────────────────┼──────────┼───────────────────┼───────────────┤
│ libwebp6     │ CVE-2023-4863  │ CRITICAL │ 0.6.1-2.1         │ 0.6.1-2.1+deb11u2 │
│ openssl      │ CVE-2023-0286  │ HIGH     │ 1.1.1n-0+deb11u3  │ 1.1.1n-0+deb11u4  │
│ ...          │                │          │                   │               │
└──────────────┴────────────────┴──────────┴───────────────────┴───────────────┘

Now the current Alpine-based tag:

trivy image --severity HIGH,CRITICAL nginx:1.27-alpine
nginx:1.27-alpine (alpine 3.20)
Total: 0 (HIGH: 0, CRITICAL: 0)

(Exact counts change every day as new CVEs are published and images are rebuilt. Run it yourself to see today's numbers.)

Friends, look at that difference. Same web server, but the old image carries a critical libwebp bug (CVE-2023-4863, the one used in real attacks against browsers in 2023). The fix was not a code change. It was choosing a fresh, smaller base image.

How does Trivy find vulnerabilities?

Trivy image scan Trivy reads the image layers, compares packages with its CVE database and prints a table. CI fails on HIGH or CRITICAL. Trivy image scan Imagenginx:1.27LayerspackagesCVE DBcompareReportHIGH/CRITICALCI gatepass or fail you Scan every image before it reaches the registry or the cluster

Trivy compares the packages inside the image with a CVE database, and CI can block HIGH/CRITICAL.

An image is a stack of layers. Trivy reads them and builds a list of everything installed: Debian or Alpine packages (apt, apk), plus app libraries such as Java .jar files, package-lock.json, requirements.txt, go.sum, Gemfile.lock and composer.lock. It then matches each name and version with its vulnerability database, which is built from sources like the NVD and the Debian, Alpine and GitHub security advisories.

How do I scan step by step?

  1. Install Trivy (apt or rpm repo, brew install trivy, or the Docker image).
  2. Run trivy image <name:tag>.
  3. Read the Total line first.
  4. Re-run with --severity HIGH,CRITICAL --ignore-unfixed.
  5. For each row, note the Fixed Version.
  6. Upgrade the base image or the library, then rebuild.
  7. Scan again and compare the totals.
  8. Add the scan to CI with --exit-code 1.

What Trivy finds in each language

Stack File Trivy reads Example finding
Java / Spring .jar files in the image log4j-core 2.14 → CVE-2021-44228 (Log4Shell)
Node.js package-​lock.​json, node_modules old lodash → prototype pollution CVEs
Python requirements.txt, site-packages old urllib3 / requests CVEs
Go Go binary build info, go.sum old golang.org/x/net HTTP/2 CVEs
PHP composer.lock old guzzlehttp/​guzzle CVEs
Ruby Gemfile.lock old nokogiri CVEs
.NET *.deps.json old System.​Text.​Encodings.​Web CVEs
OS layer dpkg / apk / rpm database openssl, glibc, zlib, libwebp

Add Trivy to a CI pipeline

GitHub Actions

- name: Scan image
  uses: aquasecurity/trivy-action@0.24.0
  with:
    image-ref: myapp:${{ github.sha }}
    severity: HIGH,CRITICAL
    ignore-unfixed: true
    exit-code: '1'

GitLab CI or Jenkins (shell step)

trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed myapp:$BUILD_NUMBER

Start with CRITICAL only, so the team is not flooded, then add HIGH once the backlog is clean.

Scan more than images

trivy fs --scanners vuln,secret,misconfig .     # your source folder
trivy config k8s/                               # Kubernetes YAML
trivy config terraform/                         # Terraform

trivy config warns about things like containers running as root, missing resource limits and S3 buckets without encryption.

Scan in Amazon ECR

  1. Open ECR → your repository → Edit.
  2. Turn on Scan on push (basic scanning).
  3. For deeper checks, go to ECR → Private registry → Scanning configuration → Enhanced scanning.
  4. Enhanced scanning uses Amazon Inspector, includes language libraries, and re-scans when new CVEs come out.
  5. View findings in ECR or in Amazon Inspector.

Google Artifact Registry and Azure Container Registry (with Microsoft Defender for Containers) offer the same kind of scanning.

Real incidents this would have caught

  • Log4Shell (CVE-2021-44228), December 2021: teams with image scanning could find every image with a vulnerable log4j-core in minutes. Teams without it searched servers by hand for days.
  • xz-utils backdoor (CVE-2024-3094), March 2024: a backdoor in xz versions 5.6.0 and 5.6.1 was found by a Microsoft engineer before it spread widely. Scanners quickly added the CVE, and teams could prove their images used safe versions.

Mistakes to avoid

  1. Scanning once and forgetting. New CVEs appear every day. Re-scan running images on a schedule, or use ECR enhanced scanning.
  2. Failing on every LOW finding. Developers start ignoring the scanner. Gate on what matters.
  3. Treating zero findings as "secure". A scanner only knows published issues.

Summary table

Task Command
Scan an image trivy image nginx:​1.​27
Only serious, fixable --​severity HIGH,​CRITICAL --​ignore-​unfixed
Fail CI --exit-code 1
Secrets + config in repo trivy fs --​scanners secret,​misconfig .
Kubernetes / Terraform trivy config <folder>
Registry scanning ECR scan on push / enhanced scanning

Quick quiz: check what you learned

  1. What does Trivy compare an image against?

    1. A database of known CVEs
    2. The Docker Hub star ratings
    3. The kubelet runtime logs
    4. The EC2 security group rules
    Show answer

    A. Trivy lists packages in the image and matches them with published CVEs.

  2. Which flag makes a CI job fail when issues are found?

    1. --exit-code 1
    2. --format table
    3. --quiet mode on
    4. --cache-dir /tmp
    Show answer

    A. With --exit-code 1, Trivy returns failure when findings match your filters.

  3. What does --ignore-unfixed hide from the report?

    1. CVEs with no fix available
    2. All of the LOW findings
    3. Secrets found in the layers
    4. Misconfigured Kubernetes YAML
    Show answer

    A. It removes findings that cannot be fixed by upgrading yet.

  4. Which ECR option re-scans images when new CVEs appear?

    1. Enhanced scanning (Inspector)
    2. Basic scan on push only
    3. Lifecycle policy rules
    4. Cross-region replication
    Show answer

    A. Enhanced scanning keeps checking images continuously with Amazon Inspector.

Learn it properly

This guide is the short path. These pages go deeper, with labs:

Frequently asked questions

What is Trivy?

Trivy is a free, open-source scanner from Aqua Security. It finds known vulnerabilities (CVEs) in OS packages and app libraries inside images, plus secrets and misconfigurations.

Does Trivy need internet access?

It downloads a vulnerability database on first run and updates it every few hours. For offline use you can mirror the database.

What does --ignore-unfixed do?

It hides vulnerabilities that have no fixed version yet, so the report shows only what you can fix today.

Is a scan with zero CVEs proof the image is safe?

No. A scanner only finds known, published issues. You still need least privilege, non-root users and patching.

How is ECR scanning different?

Basic ECR scanning checks OS packages on push. Enhanced scanning uses Amazon Inspector, covers language libraries and re-scans when new CVEs come out.

Can I scan Kubernetes YAML and Terraform?

Yes. trivy config . checks Dockerfiles, Kubernetes manifests and Terraform for risky settings.