A Trivy scan inspects your Dockerfile’s base image to find unresolved vulnerabilities that your containers will inherit. Trivy can also look at operating system packages and source code dependencies added via popular package managers.
Trivy has three scan types: container, Git repository, and filesystem directory. We’re focusing on container scans in this article. The Trivy docs provide more information on how you can analyze your source code and its environment.
Installing Trivy
Trivy’s available on most popular Linux distributions. You might need to add the developer’s repository. You can find the right link for your distribution in the Trivy docs.
If you’d prefer to use a specific version, you can download a binary from the project’s GitHub releases page. There’s also an automated install script that will download the appropriate binary for your operating system.
Finally, Trivy’s got its own Docker image which you can use instead of bare-metal installation:
This command binds your trivy-cache directory to the Trivy container’s cache path. This improves performance by allowing Trivy to cache data outside of Docker between scans.
Your host’s Docker socket also gets mounted into the container. This lets Trivy scan other containers running on the host. Now you’re ready to start finding vulnerabilities.
First Run
Trivy’s container engine supports local and remote images. It works with Docker, Podman, exported image archives (docker save) and images in registries such as Docker Hub and GitHub Container Registry.
You can start a basic scan using the trivy image command. This accepts an image tag.
Trivy will download its vulnerability database on the first run. The database will be cached and reused for future scans.
Scan results are emitted straight to your terminal. The summary at the top shows the detected container operating system and a breakdown of found vulnerabilities by severity. The table provides a full list of issues, including the library each one was found in, a description, and a CVE ID when available.
Reducing the Noise
Trivy supports several flags to let you customize its output. It will default to showing all detected vulnerabilities if no flags are present. This could include vulnerabilities that haven’t been patched in the upstream project.
You can exclude unfixed issues by adding the –ignore-unfixed flag. This reduces the noise by hiding problems that you won’t be able to resolve.
Sometimes you might want to intentionally accept a vulnerability. Not all issues impact all projects equally. If you’re not affected, or you’re willing to take the risk, Trivy will let you omit specific CVE IDs from your scans.
Add a .trivyignore file to your working directory. Enter a list of CVE IDs, one on each line. Trivy will find and use the file when you run a scan. CVEs that are present in .trivyignore won’t show up in the scan output. It’s a good idea to add a comment to each CVE you exclude; this ensures other contributors are informed why the risk has been accepted.
Filtering Vulnerabilities
You can filter to show vulnerabilities of a particular type using the –vuln-type flag. This accepts either library or os as a value.
Using library will reveal issues arising from programming language dependencies. The os option scopes the scan to operating system packages.
You can also filter by vulnerability severity. This helps you focus on the issues that matter by hiding relatively insignificant vulnerabilities. Pass in a comma-separated list of CVSS severity levels to include:
Now any “low” severity problems will be omitted from the report.
Trivy defaults to a visual table designed for human consumption in a terminal. You can get machine-parsable JSON instead by adding –format json.
There’s also support for customized output styles using templates. Several templates are included, such as xml and html:
This scan will produce an HTML report saved to scan.html. Graphical reports can be quicker to read and easier to share, especially when many issues are found.
Using Trivy In CI
You can easily incorporate Trivy into your CI scripts. Beware that the exit code is always 0 by default, even if vulnerabilities are found. Add the –exit-code 1 flag to make Trivy exit with a non-zero code if issues are present.
You’ve got multiple options to get Trivy into your builds. Official integration patterns are available for popular CI providers including GitHub, GitLab, Travis, and CircleCI.
When you build images within your pipeline, you can either run Trivy on the final build output or use the tool within the container. Docker’s multi-stage builds let you reference the Trivy image and abort the build if a scan fails. Make sure you use the filesystem mode instead of image, as you’re scanning the running container from the inside.
It’s usually best to run Trivy near the end of your Dockerfile, after all your software dependencies are installed. Run rm /usr/local/bin/trivy afterward to reduce the size of your final image.
Server Mode
Trivy can run in client-server mode. This moves the vulnerability database to the server, so clients don’t need to maintain their own versions.
Trivy binaries come with server mode built-in. Run trivy server to start a server instance on your machine. The default port is 4594; you can change this by adding –listen localhost:8080 and specifying the chosen port.
The server will download the vulnerability database when it starts. It’ll check for updates in the background and automatically pull new versions.
You connect a Trivy client to your server using trivy client:
If you need authentication, add a –token flag to the server and the client commands. The server will only accept new clients if they present the correct token.
Summary
Using Trivy to scan your Docker containers helps you find vulnerabilities before they become an issue in production. You can be more confident in your containers by regularly checking for outdated OS packages and programming language dependencies.
Trivy acquires its vulnerability lists from several different sources. Some of those sources specify non-commercial use only, so you should check that your project’s compliant before you add Trivy to your builds.