Feedback

Chat Icon

DevSecOps in Practice

A Hands-On Guide to Operationalizing DevSecOps at Scale

Detecting Vulnerabilities in Docker Images
58%

Scanning Docker Images with Trivy

Trivy is one of the most popular open-source tools that, among other features, scans Docker images for vulnerabilities. It supports scanning images stored in local registries, remote registries, and container runtimes. It uses vulnerability databases like NVD, Red Hat Security Data, and Ubuntu CVE Tracker to identify known vulnerabilities in the image layers.

To use Trivy, you can run it as a standalone tool or integrate it into your CI/CD pipeline. In this section, we will demonstrate how to install, configure, and use Trivy. Let's start with the installation.

The easiest way to install Trivy is by using the installation script that installs Trivy from GitHub Release:

# Configure the version you want to install
VERSION=v0.60.0

# Install Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | \
    sudo sh -s -- -b \
    /usr/local/bin \
    $VERSION

When it comes to image scanning, Trivy supports 2 distinct targets:

  • Files inside container images: This includes scanning the filesystem of the image for vulnerabilities, misconfigurations, and secrets.
  • Container image metadata: Every container image has metadata that describes the image, such as the layers, labels, and environment variables. Trivy can scan this metadata for vulnerabilities and misconfigurations.

To scan a Docker image with Trivy, you can use the following command:

# Scan a Docker image
trivy image 

If you want to enable only vulnerability scanning, you can use --scanners vuln.

trivy image --scanners vuln 

To filter vulnerabilities by severity, you can use the --severity flag. For example, to only keep high and critical vulnerabilities, you can run:

trivy image --severity HIGH,CRITICAL 

We can also ignore specific CVEs using a file .trivyignore in the root directory of the project. This is an example that ignores CVE-2022-40897:

# .trivyignore
CVE-2022-40897

It is also possible to filter by type of vulnerability, such as OS or library vulnerabilities:

# Scan for OS vulnerabilities
trivy image --vuln-type os 

# Scan for library vulnerabilities
trivy image --vuln-type library 

The default output of a scan is a table, but you can also generate JSON, template, or machine-friendly output formats. Here are some examples:

# Scan and output the results in JSON format
trivy image --format json 

# Scan and output the results in template format
trivy image --format template --template "{{ range . }} {{ .Target }} {{ end }}" 

# A second example of template format that counts the number of critical and high vulnerabilities
trivy image --format template --template '{{- $critical := 0 }}{{- $high := 0 }}{{- range . }}{{- range .Vulnerabilities }}{{- if  eq .Severity "CRITICAL" }}{{- $critical = add $critical 1 }}{{- end }}{{- if  eq .Severity "HIGH" }}{{- $high = add $high 1 }}{{- end }}{{- end }}{{- end }}Critical: {{ $critical }}, High: {{ $high }}' 

You can find out more about the available formats in the official documentation.

In CI/CD pipelines, you have the option to fail the build if vulnerabilities are found. This can be achieved by using the --exit-code flag:

# Fail the build if vulnerabilities are found
trivy image --exit-code 1 

We have these images available for scanning:

  • $GITLAB_REGISTRY_URL/menu-service:v0.1.0
  • $GITLAB_REGISTRY_URL/qr-service:v0.1.0
  • $GITLAB_REGISTRY_URL/menu-postgresql:v0.1.0

We can scan them using the following commands (we will only scan for high and critical vulnerabilities):

# Scan the menu service image
trivy image \
    --severity HIGH,CRITICAL \
    --vuln-type os,library \
    $GITLAB_REGISTRY_URL/menu-service:v0.1.0 \
    --exit-code 1 \
    -f json

# Scan the qr service image
trivy image \
    --severity HIGH,CRITICAL \
    --vuln-type os,library \    
    $GITLAB_REGISTRY_URL/qr-service:v0.1.0 \
    --exit-code 1 \
    -f json

# Scan the menu-postgresql image
trivy image \
    --severity HIGH,CRITICAL \
    --vuln-type os,library \    
    $GITLAB_REGISTRY_URL/menu-postgresql:v0.1.0 \
    --exit-code 1 \
    -f json

Understanding Trivy Reports

The table report format is more human-readable, but the JSON format is easier to parse and integrate into CI/CD pipelines. In our case, the JSON report should contain two key sections:

  • os-pkgs: Lists vulnerabilities in operating system packages (e.g., Debian, Ubuntu, Alpine packages installed via apt, yum, apk).
  • lang-pkgs: Lists vulnerabilities in language-specific application dependencies (e.g., Python packages installed via pip, Node.js dependencies via npm).

Example:

[
  {
    "Target": "registry.gitlab.com/restqr/restqr/menu-service:v0.1.0 (debian 12.9)",
    "Class": "os-pkgs",
    "Type": "debian",
    "Vulnerabilities": [
        // trunca

DevSecOps in Practice

A Hands-On Guide to Operationalizing DevSecOps at Scale

Enroll now to unlock all content and receive all future updates for free.