Trivy: scanning your containers for vulnerabilities
Tags: security, containers, kubernetes
Published: 2021-02-21 17:03:29

Originally published on [mccricardo.com](https://mccricardo.com/trivy/).

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](https://github.com/aquasecurity/trivy).

[Trivy](https://github.com/aquasecurity/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](https://github.com/aquasecurity/trivy#continuous-integration-ci).

## A simple example
To exemplify Trivy's usage, well install it locally and scan a popular container for vulnerabilities.

### Installation
```sh
# 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.

```sh
~ 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.

```sh
~ 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.

```sh
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?

```sh
~ 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
# 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.

```sh
~ 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](https://github.com/aquasecurity/trivy#examples) to better grasp all it can do for us and how to integrate it into our pipelines.