In software, a vulnerability is a weakness or a glitch that can be targeted with the intent of exploiting the system. When done by a bad actor, that exploitation aims at making us look bad, making our projects look bad, making our companies look bad. That can translate into a loss of credibility (and revenue) and, in some extreme cases, can be the “death” of a company.

Shift left security refers to moving security sooner in the development process. It aims at having security in mind from the get-go and not when “sh*t hits the fan”. One tool that can help us with securing our systems is Trivy.

Trivy is a vulnerability scanner for containers (among other artifacts) that detects vulnerabilities of OS packages and application dependencies. It’s easy to use and, as such, quite simple to add to our CI pipelines.

A simple example

To exemplify Trivy’s usage, well install it locally and scan a popular container for vulnerabilities.

Installation

# 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

Let’s ensure Trivy is installed and ready to go.

~ trivy -h
NAME:
   trivy - A simple and comprehensive vulnerability scanner for containers

USAGE:
   trivy [global options] command [command options] target

VERSION:
   0.16.0

COMMANDS:
   image, i          scan an image
   filesystem, fs    scan local filesystem
   repository, repo  scan remote repository
   client, c         client mode
   server, s         server mode
   help, h           Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --quiet, -q        suppress progress bar and log output (default: false) [$TRIVY_QUIET]
   --debug, -d        debug mode (default: false) [$TRIVY_DEBUG]
   --cache-dir value  cache directory (default: "/root/.cache/trivy") [$TRIVY_CACHE_DIR]
   --help, -h         show help (default: false)
   --version, -v      print the version (default: false)

Scan an image

Let’s scan a popular image, alpine:3.13.2.

~ trivy image alpine:3.13.2
2021-02-21T16:17:45.678Z    INFO    Detecting Alpine vulnerabilities...
2021-02-21T16:17:45.678Z    INFO    Trivy skips scanning programming language libraries because no supported file was detected

alpine:3.13.2 (alpine 3.13.2)
=============================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

Alpine Linux is a small image, having a small attack surface. Let’s try a slightly bigger one, redis:6.0.10-alpine.

trivy image redis:6.0.10-alpine
2021-02-21T16:26:43.485Z    INFO    Detecting Alpine vulnerabilities...
2021-02-21T16:26:43.487Z    INFO    Trivy skips scanning programming language libraries because no supported file was detected

redis:6.0.10-alpine (alpine 3.13.2)
===================================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

What if we scan the same redis image but based on Debian Buster, redis:6.0.10-buster?

~ trivy image redis:6.0.10-buster
2021-02-21T16:26:08.488Z    INFO    Detecting Debian vulnerabilities...
2021-02-21T16:26:08.494Z    INFO    Trivy skips scanning programming language libraries because no supported file was detected

redis:6.0.10-buster (debian 10.8)
=================================
Total: 94 (UNKNOWN: 0, LOW: 66, MEDIUM: 9, HIGH: 19, CRITICAL: 0)

+----------------+---------------------+----------+-------------------+------------------+------------------------------------------------------------+
|    LIBRARY     |  VULNERABILITY ID   | SEVERITY | INSTALLED VERSION |  FIXED VERSION   |                           TITLE                            |
+----------------+---------------------+----------+-------------------+------------------+------------------------------------------------------------+
| apt            | CVE-2011-3374       | LOW      | 1.8.2.2           |                  | It was found that apt-key in apt,                          |
|                |                     |          |                   |                  | all versions, do not correctly...                          |
|                |                     |          |                   |                  | -->avd.aquasec.com/nvd/cve-2011-3374                       |
+----------------+---------------------+          +-------------------+------------------+------------------------------------------------------------+
| bash           | CVE-2019-18276      |          | 5.0-4             |                  | bash: when effective UID is not                            |
|                |                     |          |                   |                  | equal to its real UID the...                               |
|                |                     |          |                   |                  | -->avd.aquasec.com/nvd/cve-2019-18276                      |
+                +---------------------+          +                   +------------------+------------------------------------------------------------+
|                | TEMP-0841856-B18BAF |          |                   |                  | -->security-tracker.debian.org/tracker/TEMP-0841856-B18BAF |
+----------------+---------------------+          +-------------------+------------------+------------------------------------------------------------+
| coreutils      | CVE-2016-2781       |          | 8.30-3            |                  | coreutils: Non-privileged                                  |
|                |                     |          |                   |                  | session can escape to the                                  |
|                |                     |          |                   |                  | parent session in chroot                                   |
|                |                     |          |                   |                  | -->avd.aquasec.com/nvd/cve-2016-2781                       |
+                +---------------------+          +                   +------------------+------------------------------------------------------------+
|                | CVE-2017-18018      |          |                   |                  | coreutils: race condition                                  |
|                |                     |          |                   |                  | vulnerability in chown and chgrp                           |
|                |                     |          |                   |                  | -->avd.aquasec.com/nvd/cve-2017-18018                      |
+----------------+---------------------+----------+-------------------+------------------+------------------------------------------------------------+
| gcc-8-base     | CVE-2018-12886      | HIGH     | 8.3.0-6           |                  | gcc: spilling of stack                                     |
|                |                     |          |                   |                  | protection address in cfgexpand.c                          |
|                |                     |          |                   |                  | and function.c leads to...                                 |
|                |                     |          |                   |                  | -->avd.aquasec.com/nvd/cve-2018-12886                      |
+                +---------------------+          +                   +------------------+------------------------------------------------------------+
|                | CVE-2019-15847      |          |                   |                  | gcc: POWER9 "DARN" RNG intrinsic                           |
|                |                     |          |                   |                  | produces repeated output                                   |
|                |                     |          |                   |                  | -->avd.aquasec.com/nvd/cve-2019-15847                      |
+----------------+---------------------+----------+-------------------+------------------+------------------------------------------------------------+

(output abbreviated)

As we can see, there’s a lot more going on this time. Easy integration into our pipelines would be to produce an image and have Trivy scan it for vulnerabilities.

# Dockerfile
FROM alpine:3.13.2
RUN apk add --no-cache bash
CMD ["/bin/bash", "-c" "echo hello world"]

We can now build and scan this image for vulnerabilities.

~ docker build -t test-trivy:latest .
Sending build context to Docker daemon    178MB
Step 1/3 : FROM alpine:3.13.2
3.13.2: Pulling from library/alpine
ba3557a56b15: Pull complete 
Digest: sha256:a75afd8b57e7f34e4dad8d65e2c7ba2e1975c795ce1ee22fa34f8cf46f96a3be
Status: Downloaded newer image for alpine:3.13.2
 ---> 28f6e2705743
Step 2/3 : RUN apk add --no-cache bash
 ---> Running in cb3c8b38fd8a
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
(1/4) Installing ncurses-terminfo-base (6.2_p20210109-r0)
(2/4) Installing ncurses-libs (6.2_p20210109-r0)
(3/4) Installing readline (8.1.0-r0)
(4/4) Installing bash (5.1.0-r0)
Executing bash-5.1.0-r0.post-install
Executing busybox-1.32.1-r3.trigger
OK: 8 MiB in 18 packages
Removing intermediate container cb3c8b38fd8a
 ---> d5a4d26a6bc7
Step 3/3 : CMD ["/bin/bash", "-c" "echo hello world"]
 ---> Running in 3506ff18b2c9
Removing intermediate container 3506ff18b2c9
 ---> 29a626fcb44e
Successfully built 29a626fcb44e
Successfully tagged test-trivy:latest
~ trivy  image test-trivy:latest
2021-02-21T16:37:40.334Z    WARN    You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
2021-02-21T16:37:40.438Z    INFO    Detecting Alpine vulnerabilities...
2021-02-21T16:37:40.444Z    INFO    Trivy skips scanning programming language libraries because no supported file was detected

test-trivy:latest (alpine 3.13.2)
=================================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

There’s a lot that Trivy can do to help us secure our systems. Take a look at its examples section to better grasp all it can do for us and how to integrate it into our pipelines.