Trivy (tri pronounced like trigger, vy pronounced like envy) is a simple and comprehensive vulnerability scanner for containers. A software vulnerability is a glitch, flaw, or weakness present in the software or in an Operating System. Trivy detects vulnerabilities of OS packages (Alpine, RHEL, CentOS, etc.) and application dependencies (Bundler, Composer, npm, yarn etc.). Trivy is easy to use. Just install the binary and you’re ready to scan. All you need to do for scanning is to specify an image name of the container.
Demo
Features
- Detect comprehensive vulnerabilities
- OS packages (Alpine, Red Hat Universal Base Image, Red Hat Enterprise Linux, CentOS, Debian, Ubuntu, Amazon Linux and Distroless)
- Application dependencies (Bundler, Composer, Pipenv, Poetry, npm, yarn and Cargo)
- Simple
- Specify only an image name
- See Quick Start and Examples
- Easy installation
apt-get install,yum installandbrew installis possible (See Installation)- No pre-requisites such as installation of DB, libraries, etc. (The exception is that you need
rpminstalled to scan images based on RHEL/CentOS. This is automatically included if you use our installers or the Trivy container image. See Vulnerability Detection for background information.)
- High accuracy
- Especially Alpine Linux and RHEL/CentOS
- Other OSes are also high
- DevSecOps
- Suitable for CI such as Travis CI, CircleCI, Jenkins, etc.
- See CI Example
Quick Start
Simply specify an image name (and a tag). The latest tag should be avoided as problems occur with the image cache. See Clear image caches.
Basic
$ trivy [YOUR_IMAGE_NAME]
For example:
$ trivy python:3.4-alpine
Docker
Replace [YOUR_CACHE_DIR] with the cache directory on your machine.
$ docker run --rm -v [YOUR_CACHE_DIR]:/root/.cache/ aquasec/trivy [YOUR_IMAGE_NAME]
Examples
Scan an image
Simply specify an image name (and a tag).
$ trivy knqyf263/vuln-image:1.2.3
Filter the vulnerabilities by severities
$ trivy --severity HIGH,CRITICAL ruby:2.3.0
Skip update of vulnerability DB
Trivy always updates its vulnerability database when it starts operating. This is usually fast, as it is a difference update. But if you want to skip even that, use the --skip-update option.
$ trivy --skip-update python:3.4-alpine3.9
Update only specified distributions
By default, Trivy always updates its vulnerability database for all distributions. Use the --only-update option if you want to name specified distributions to update.
$ trivy --only-update alpine,debian python:3.4-alpine3.9
$ trivy --only-update alpine python:3.4-alpine3.9
Only download vulnerability database
You can also ask Trivy to simply retrieve the vulnerability database. This is useful to initialize workers in Continuous Integration systems. In the first run, the --only-update option is silently ignored.
$ trivy --download-db-only
$ trivy --download-db-only --only-update alpine
Ignore unfixed vulnerabilities
By default, Trivy also detects unpatched/unfixed vulnerabilities. This means you can’t fix these vulnerabilities even if you update all packages. If you would like to ignore them, use the --ignore-unfixed option.
$ trivy --ignore-unfixed ruby:2.3.0
Specify exit code
By default, Trivy exits with code 0 even when vulnerabilities are detected. Use the --exit-code option if you want to exit with a non-zero exit code.
$ trivy --exit-code 1 python:3.4-alpine3.9
This option is useful for CI/CD. In the following example, the test will fail only when a critical vulnerability is found.
$ trivy --exit-code 0 --severity MEDIUM,HIGH ruby:2.3.0
$ trivy --exit-code 1 --severity CRITICAL ruby:2.3.0
Ignore the specified vulnerabilities
Use .trivyignore.
$ cat .trivyignore
# Accept the risk
CVE-2018-14618
# No impact in our settings
CVE-2019-1543
$ trivy python:3.4-alpine3.9
Specify cache directory
$ trivy --cache-dir /tmp/trivy/ python:3.4-alpine3.9
Clear image caches
The --clear-cache option removes image caches. This option is useful if the image which has the same tag is updated (such as when using latest tag).
$ trivy --clear-cache python:3.7
Reset
The --reset option removes all caches and database. After this, it takes a long time as the vulnerability database needs to be rebuilt locally.
$ trivy --reset
Continuous Integration (CI)
Scan your image built in Travis CI/CircleCI. The test will fail if a vulnerability is found. When you don’t want to fail the test, specify --exit-code 0 .
Note: It will take a while for the first time (faster by cache after the second time).
Travis CI
$ cat .travis.yml
services:
- docker
env:
global:
- COMMIT=${TRAVIS_COMMIT::8}
before_install:
- docker build -t trivy-ci-test:${COMMIT} .
- export VERSION=$(curl --silent "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
- wget https://github.com/aquasecurity/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz
- tar zxvf trivy_${VERSION}_Linux-64bit.tar.gz
script:
- ./trivy --exit-code 0 --severity HIGH --no-progress --auto-refresh trivy-ci-test:${COMMIT}
- ./trivy --exit-code 1 --severity CRITICAL --no-progress --auto-refresh trivy-ci-test:${COMMIT}
cache:
directories:
- $HOME/.cache/trivy
Example: https://travis-ci.org/aquasecurity/trivy-ci-test
Repository: https://github.com/aquasecurity/trivy-ci-test
CircleCI
$ cat .circleci/config.yml
jobs:
build:
docker:
- image: docker:18.09-git
steps:
- checkout
- setup_remote_docker
- restore_cache:
key: vulnerability-db
- run:
name: Build image
command: docker build -t trivy-ci-test:${CIRCLE_SHA1} .
- run:
name: Install trivy
command: |
apk add --update curl
VERSION=$(
curl --silent "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | \
grep '"tag_name":' | \
sed -E 's/.*"v([^"]+)".*/\1/'
)
wget https://github.com/aquasecurity/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz
tar zxvf trivy_${VERSION}_Linux-64bit.tar.gz
mv trivy /usr/local/bin
- run:
name: Scan the local image with trivy
command: trivy --exit-code 0 --no-progress --auto-refresh trivy-ci-test:${CIRCLE_SHA1}
- save_cache:
key: vulnerability-db
paths:
- $HOME/.cache/trivy
workflows:
version: 2
release:
jobs:
- build
Example: https://circleci.com/gh/aquasecurity/trivy-ci-test
Repository: https://github.com/aquasecurity/trivy-ci-test
GitLab
$ cat .gitlab-ci.yml
stages:
- test
trivy:
stage: test
image: docker:stable-git
before_script:
- docker build -t trivy-ci-test:${CI_COMMIT_REF_NAME} .
- export VERSION=$(curl --silent "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
- wget https://github.com/aquasecurity/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz
- tar zxvf trivy_${VERSION}_Linux-64bit.tar.gz
variables:
DOCKER_DRIVER: overlay2
allow_failure: true
services:
- docker:stable-dind
script:
- ./trivy --exit-code 0 --severity HIGH --no-progress --auto-refresh trivy-ci-test:${CI_COMMIT_REF_NAME}
- ./trivy --exit-code 1 --severity CRITICAL --no-progress --auto-refresh trivy-ci-test:${CI_COMMIT_REF_NAME}
cache:
directories:
- $HOME/.cache/trivy
Authorization for Private Docker Registry
Trivy can download images from a private registry, without installing Docker or any other 3rd party tools. That’s because it’s easy to run in a CI process.
All you have to do is install Trivy and set ENV vars. But, I can’t recommend using ENV vars in your local machine to you.
Docker Hub
Docker Hub needs TRIVY_AUTH_URL, TRIVY_USERNAME and TRIVY_PASSWORD. You don’t need to set ENV vars when download from public repository.
export TRIVY_AUTH_URL=https://registry.hub.docker.com
export TRIVY_USERNAME={DOCKERHUB_USERNAME}
export TRIVY_PASSWORD={DOCKERHUB_PASSWORD}
Amazon ECR (Elastic Container Registry)
Trivy uses AWS SDK. You don’t need to install aws CLI tool. You can use AWS CLI’s ENV Vars.
GCR (Google Container Registry)
Trivy uses Google Cloud SDK. You don’t need to install gcloud command.
If you want to use target project’s repository, you can settle via GOOGLE_APPLICATION_CREDENTIAL.
# must set TRIVY_USERNAME empty char
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credential.json
Self Hosted Registry (BasicAuth)
BasicAuth server needs TRIVY_USERNAME and TRIVY_PASSWORD.
export TRIVY_USERNAME={USERNAME}
export TRIVY_PASSWORD={PASSWORD}
# if you want to use 80 port, use NonSSL
export TRIVY_NON_SSL=true
Vulnerability Detection
OS Packages
The unfixed/unfixable vulnerabilities mean that the patch has not yet been provided on their distribution.
| OS | Supported Versions | Target Packages | Detection of unfixed vulnerabilities |
|---|---|---|---|
| Alpine Linux | 2.2 - 2.7, 3.0 - 3.10 | Installed by apk | NO |
| Red Hat Universal Base Image | 7, 8 | Installed by yum/rpm | YES |
| Red Hat Enterprise Linux | 6, 7, 8 | Installed by yum/rpm | YES |
| CentOS | 6, 7 | Installed by yum/rpm | YES |
| Amazon Linux | 1, 2 | Installed by apt/apt-get/dpkg | NO |
| Debian GNU/Linux | wheezy, jessie, stretch, buster | Installed by apt/apt-get/dpkg | YES |
| Ubuntu | 12.04, 14.04, 16.04, 18.04, 18.10, 19.04 | Installed by apt/apt-get/dpkg | YES |
| Distroless | Any | Installed by apt/apt-get/dpkg | YES |
RHEL, CentOS and Amazon Linux package information is stored in a binary format, and Trivy uses the rpm executable to parse this information when scanning an image based on RHEL or CentOS. The Trivy container image includes rpm, and the installers include it as a dependency. If you installed the trivy binary using wget or curl, or if you build it from source, you will also need to ensure that rpm is available.
Distroless: https://github.com/GoogleContainerTools/distroless
Application Dependencies
Trivy automatically detects the following files in the container and scans vulnerabilities in the application dependencies.
- Gemfile.lock
- Pipfile.lock
- poetry.lock
- composer.lock
- package-lock.json
- yarn.lock
- Cargo.lock
The path of these files does not matter.
Example: https://github.com/aquasecurity/trivy-ci-test/blob/master/Dockerfile
Image Tar format
Trivy scans a tar image with the following format.
- Docker Image Specification (https://github.com/moby/moby/tree/master/image/spec)
- Moby Project (https://github.com/moby/moby/)
- Buildah, Podman (https://github.com/containers/buildah)
- img (https://github.com/genuinetools/img)
- Kaniko
- Kaniko (https://github.com/GoogleContainerTools/kaniko)
Data source
- PHP
- https://github.com/FriendsOfPHP/security-advisories
- Python
- https://github.com/pyupio/safety-db
- Ruby
- https://github.com/rubysec/ruby-advisory-db
- Node.js
- https://github.com/nodejs/security-wg
- Rust
- https://github.com/RustSec/advisory-db
Usage
NAME:
trivy - A simple and comprehensive vulnerability scanner for containers
USAGE:
trivy [options] image_name
VERSION:
0.1.6
OPTIONS:
--format value, -f value format (table, json) (default: "table")
--input value, -i value input file path instead of image name
--severity value, -s value severities of vulnerabilities to be displayed (comma separated) (default: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL")
--output value, -o value output file name
--exit-code value Exit code when vulnerabilities were found (default: 0)
--skip-update skip db update
--only-update value update db only specified distribution (comma separated)
--reset remove all caches and database
--clear-cache, -c clear image caches
--quiet, -q suppress progress bar and log output
--no-progress suppress progress bar
--ignore-unfixed display only fixed vulnerabilities
--refresh refresh DB (usually used after version update of trivy)
--auto-refresh refresh DB automatically when updating version of trivy
--debug, -d debug mode
--vuln-type value comma-separated list of vulnerability types (os,library) (default: "os,library")
--cache-dir value cache directory (default: "/path/to/cache")
--help, -h show help
--version, -v print the version
Comparison with other scanners
Overview
| Scanner | OS Packages | Application Dependencies | Easy to use | Accuracy | Suitable for CI |
|---|---|---|---|---|---|
| Trivy | ◯ | ◯ | ◯ | ◎ | ◯ |
| Clair | ◯ | × | △ | ◯ | △ |
| Anchore Engine | ◯ | △ | △ | ◯ | △ |
| Quay | ◯ | × | ◯ | ◯ | × |
| MicroScanner | ◯ | × | ◯ | ◯ | ◯ |
| Docker Hub | ◯ | × | ◯ | × | × |
| GCR | ◯ | × | ◯ | ◯ | × |
vs Clair
Clair uses alpine-secdb. However, the purpose of this database is to make it possible to know what packages has backported fixes. As README says, it is not a complete database of all security issues in Alpine.
Trivy collects vulnerability information in Alpine Linux from Alpine Linux aports repository. Then, those vulnerabilities will be saved on vuln-list.
alpine-secdb has 6959 vulnerabilities (as of 2019/05/12). vuln-list has 11101 vulnerabilities related to Alpine Linux (as of 2019/05/12). There is a difference in detection accuracy because the number of vulnerabilities is nearly doubled.
In addition, Trivy analyzes the middle layers as well to find out which version of the library was used for static linking.
Clair can not handle the following cases because it analyzes the image after applying all layers.
RUN apk add --no-cache sqlite-dev \
&& wget https://xxx/yyy.tar.gz \
&& tar zxvf yyy.tar.gz && cd yyy \
&& make && make install \
&& apk del sqlite-dev
And as many people know, it is difficult to select a Clair client because many clients are deprecated.
Finally, Trivy can also detect vulnerabilities in application dependent libraries such as Bundler, Composer, Pipenv, etc.
vs Anchore Engine
Similar to Clair, there is a difference in detection accuracy on Alpine Linux. Then, as noted above, Anchore Engine does not detect unfixable vulnerabilities on RHEL/CentOS, whereas Trivy does.
Also, Anchore Engine needs some steps to start scanning. Trivy is much easier to use.
vs Quay, Docker Hub, GCR
As Quay seems to use Clair internally, it has the same accuracy as Clair. Docker Hub can scan only official images. GCR hardly detects vulnerabilities on Alpine Linux. Also, it is locked to a specific registry.
Trivy can be used regardless of the registry, and it is easily integrated with CI/CD services.
Migration
On 19 August 2019, Trivy’s repositories moved from knqyf263/trivy to aquasecurity/trivy. If you previously installed Trivy you should update any scripts or package manager records as described in this section.
Overview
If you have a script that installs Trivy (for example into your CI pipelines) you should update it to obtain it from the new location by replacing knqyf263/trivy with aquasecurity/trivy.
For example:
# Before
$ wget https://github.com/knqyf263/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz
# After
$ wget https://github.com/aquasecurity/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz
Debian/Ubuntu
$ apt-get remove --purge trivy
$ sed -i s/knqyf263/aquasecurity/g /etc/apt/sources.list.d/trivy.list
$ apt-get update
$ apt-get install trivy

