Skip to content

Container Image

Trivy supports two targets for container images.

  • Files inside container images
  • Container image metadata

Files inside container images

Container images consist of files. For instance, new files will be installed if you install a package.

Trivy scans the files inside container images for

  • Vulnerabilities
  • Misconfigurations
  • Secrets
  • Licenses

By default, vulnerability and secret scanning are enabled, and you can configure that with --scanners.

Vulnerabilities

It is enabled by default. You can simply specify your image name (and a tag). It detects known vulnerabilities in your container image. See here for the detail.

$ trivy image [YOUR_IMAGE_NAME]

For example:

$ trivy image python:3.4-alpine
Result
2019-05-16T01:20:43.180+0900    INFO    Updating vulnerability database...
2019-05-16T01:20:53.029+0900    INFO    Detecting Alpine vulnerabilities...

python:3.4-alpine3.9 (alpine 3.9.2)
===================================
Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)

+---------+------------------+----------+-------------------+---------------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |             TITLE              |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| openssl | CVE-2019-1543    | MEDIUM   | 1.1.1a-r1         | 1.1.1b-r1     | openssl: ChaCha20-Poly1305     |
|         |                  |          |                   |               | with long nonces               |
+---------+------------------+----------+-------------------+---------------+--------------------------------+

To enable only vulnerability scanning, you can specify --scanners vuln.

$ trivy image --scanners vuln [YOUR_IMAGE_NAME]

Misconfigurations

It is supported, but it is not useful in most cases. As mentioned here, Trivy mainly supports Infrastructure as Code (IaC) files for misconfigurations. If your container image includes IaC files such as Kubernetes YAML files or Terraform files, you should enable this feature with --scanners misconfig.

$ trivy image --scanners misconfig [YOUR_IMAGE_NAME]

Secrets

It is enabled by default. See here for the detail.

$ trivy image [YOUR_IMAGE_NAME]

Licenses

It is disabled by default. See here for the detail.

$ trivy image --scanners license [YOUR_IMAGE_NAME]

Container image metadata

Container images have configuration. docker inspect and docker history show the information according to the configuration.

Trivy scans the configuration of container images for

  • Misconfigurations
  • Secrets

They are disabled by default. You can enable them with --image-config-scanners.

Tips

The configuration can be exported as the JSON file by docker save.

Misconfigurations

Trivy detects misconfigurations on the configuration of container images. The image config is converted into Dockerfile and Trivy handles it as Dockerfile. See here for the detail of Dockerfile scanning.

It is disabled by default. You can enable it with --image-config-scanners misconfig.

$ trivy image --image-config-scanners misconfig [YOUR_IMAGE_NAME]
Result
alpine:3.17 (dockerfile)
========================
Tests: 24 (SUCCESSES: 21, FAILURES: 3, EXCEPTIONS: 0)
Failures: 3 (UNKNOWN: 0, LOW: 2, MEDIUM: 0, HIGH: 1, CRITICAL: 0)

HIGH: Specify at least 1 USER command in Dockerfile with non-root user as argument
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile.

See https://avd.aquasec.com/misconfig/ds002
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Consider using 'COPY file:e4d600fc4c9c293efe360be7b30ee96579925d1b4634c94332e2ec73f7d8eca1 in /' command instead of 'ADD file:e4d600fc4c9c293efe360be7b30ee96579925d1b4634c94332e2ec73f7d8eca1 in /'
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
You should use COPY instead of ADD unless you want to extract a tar file. Note that an ADD command will extract a tar file, which adds the risk of Zip-based vulnerabilities. Accordingly, it is advised to use a COPY command, which does not extract tar files.

See https://avd.aquasec.com/misconfig/ds005
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 alpine:3.17:1
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1 [ ADD file:e4d600fc4c9c293efe360be7b30ee96579925d1b4634c94332e2ec73f7d8eca1 in /
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


LOW: Add HEALTHCHECK instruction in your Dockerfile
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
You shoud add HEALTHCHECK instruction in your docker container images to perform the health check on running containers.

See https://avd.aquasec.com/misconfig/ds026
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Tip

You can see how each layer is created with docker history.

Secrets

Trivy detects secrets on the configuration of container images. The image config is converted into JSON and Trivy scans the file for secrets. It is especially useful for environment variables that are likely to have credentials by accident. See here for the detail.

$ trivy image --image-config-scanners secret [YOUR_IMAGE_NAME]
Result
vuln-image (alpine 3.17.1)
==========================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)


vuln-image (secrets)
====================
Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2)

CRITICAL: GitHub (github-pat)
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
GitHub Personal Access Token
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 test:16
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  14     {
  15     "created": "2023-01-09T17:05:20Z",
  16 [   "created_by": "ENV secret=****************************************",
  17     "comment": "buildkit.dockerfile.v0",
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


CRITICAL: GitHub (github-pat)
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
GitHub Personal Access Token
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 test:34
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  32     "Env": [
  33     "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  34 [   "secret=****************************************"
  35     ]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Tip

You can see environment variables with docker inspect.

Supported

Trivy will look for the specified image in a series of locations. By default, it will first look in the local Docker Engine, then Containerd, Podman, and finally container registry.

This behavior can be modified with the --image-src flag. For example, the command

trivy image --image-src podman,containerd alpine:3.7.3

Will first search in Podman. If the image is found there, it will be scanned and the results returned. If the image is not found in Podman, then Trivy will search in Containerd. If the image is not found there either, the scan will fail and no more image sources will be searched.

Docker Engine

Trivy tries to looks for the specified image in your local Docker Engine. It will be skipped if Docker Engine is not running locally.

If your docker socket is not the default path, you can override it via DOCKER_HOST.

containerd

EXPERIMENTAL

This feature might change without preserving backwards compatibility.

Trivy tries to looks for the specified image in your local containerd. It will be skipped if containerd is not running locally.

Specify your image name in containerd running locally.

$ nerdctl images
REPOSITORY        TAG       IMAGE ID        CREATED         PLATFORM       SIZE         BLOB SIZE
aquasec/nginx    latest    2bcabc23b454    3 hours ago     linux/amd64    149.1 MiB    54.1 MiB
$ trivy image aquasec/nginx

If your containerd socket is not the default path (//run/containerd/containerd.sock), you can override it via CONTAINERD_ADDRESS.

$ export CONTAINERD_ADDRESS=/run/k3s/containerd/containerd.sock
$ trivy image aquasec/nginx

If your scan targets are images in a namespace other than containerd's default namespace (default), you can override it via CONTAINERD_NAMESPACE.

$ export CONTAINERD_NAMESPACE=k8s.io
$ trivy image aquasec/nginx

Podman

EXPERIMENTAL

This feature might change without preserving backwards compatibility.

Scan your image in Podman (>=2.0) running locally. The remote Podman is not supported. Before performing Trivy commands, you must enable the podman.sock systemd service on your machine. For more details, see here.

$ systemctl --user enable --now podman.socket

Then, you can scan your image in Podman.

$ cat Dockerfile
FROM alpine:3.12
RUN apk add --no-cache bash
$ podman build -t test .
$ podman images
REPOSITORY                TAG     IMAGE ID      CREATED      SIZE
localhost/test            latest  efc372d4e0de  About a minute ago  7.94 MB
$ trivy image test

Container Registry

Trivy supports registries that comply with the following specifications.

You can configure credentials with docker login. See here for the detail.

Tar Files

Trivy supports image tar files generated by the following tools.

$ docker pull ruby:3.1-alpine3.15
$ docker save ruby:3.1-alpine3.15 -o ruby-3.1.tar
$ trivy image --input ruby-3.1.tar
Result
2022-02-03T10:08:19.127Z        INFO    Detected OS: alpine
2022-02-03T10:08:19.127Z        WARN    This OS version is not on the EOL list: alpine 3.15
2022-02-03T10:08:19.127Z        INFO    Detecting Alpine vulnerabilities...
2022-02-03T10:08:19.127Z        INFO    Number of language-specific files: 2
2022-02-03T10:08:19.127Z        INFO    Detecting gemspec vulnerabilities...
2022-02-03T10:08:19.128Z        INFO    Detecting node-pkg vulnerabilities...
2022-02-03T10:08:19.128Z        WARN    This OS version is no longer supported by the distribution: alpine 3.15.0
2022-02-03T10:08:19.128Z        WARN    The vulnerability detection may be insufficient because security updates are not provided

ruby-3.1.tar (alpine 3.15.0)
============================
Total: 3 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 3, CRITICAL: 0)

+----------+------------------+----------+-------------------+---------------+---------------------------------------+
| LIBRARY  | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |                 TITLE                 |
+----------+------------------+----------+-------------------+---------------+---------------------------------------+
| gmp      | CVE-2021-43618   | HIGH     | 6.2.1-r0          | 6.2.1-r1      | gmp: Integer overflow and resultant   |
|          |                  |          |                   |               | buffer overflow via crafted input     |
|          |                  |          |                   |               | -->avd.aquasec.com/nvd/cve-2021-43618 |
+----------+                  +          +                   +               +                                       +
| gmp-dev  |                  |          |                   |               |                                       |
|          |                  |          |                   |               |                                       |
|          |                  |          |                   |               |                                       |
+----------+                  +          +                   +               +                                       +
| libgmpxx |                  |          |                   |               |                                       |
|          |                  |          |                   |               |                                       |
|          |                  |          |                   |               |                                       |
+----------+------------------+----------+-------------------+---------------+---------------------------------------+

Node.js (node-pkg)
==================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)


Ruby (gemspec)
==============
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

OCI Layout

Trivy supports image directories compliant with Open Container Image Layout Specification.

Buildah:

$ buildah push docker.io/library/alpine:3.11 oci:/path/to/alpine
$ trivy image --input /path/to/alpine

Skopeo:

$ skopeo copy docker-daemon:alpine:3.11 oci:/path/to/alpine
$ trivy image --input /path/to/alpine

Referencing specific images can be done by their tag or by their manifest digest:

# Referenced by tag
$ trivy image --input /path/to/alpine:3.15

# Referenced by digest
$ trivy image --input /path/to/alpine@sha256:82389ea44e50c696aba18393b168a833929506f5b29b9d75eb817acceb6d54ba

SBOM

Trivy supports the generation of Software Bill of Materials (SBOM) for container images and the search for SBOMs during vulnerability scanning.

Generation

Trivy can generate SBOM for container images. See here for the detail.

Discovery

Trivy can search for Software Bill of Materials (SBOMs) that reference container images. If an SBOM is found, the vulnerability scan is performed using the SBOM instead of the container image. By using the SBOM, you can perform a vulnerability scan more quickly, as it allows you to skip pulling the container image and analyzing its layers.

To enable this functionality, you need to specify the --sbom-sources flag. The following two sources are supported:

  • OCI Registry (oci)
  • Rekor (rekor)

Example:

$ trivy image --sbom-sources oci ghcr.io/knqyf263/oci-referrers
2023-03-05T17:36:55.278+0200    INFO    Vulnerability scanning is enabled
2023-03-05T17:36:58.103+0200    INFO    Detected SBOM format: cyclonedx-json
2023-03-05T17:36:58.129+0200    INFO    Found SBOM (cyclonedx) in the OCI referrers
...

ghcr.io/knqyf263/oci-referrers (alpine 3.16.2)
==============================================
Total: 17 (UNKNOWN: 0, LOW: 0, MEDIUM: 5, HIGH: 9, CRITICAL: 3)

The OCI Registry utilizes the Referrers API. For more information about Rekor, please refer to its documentation.

Compliance

EXPERIMENTAL

This feature might change without preserving backwards compatibility.

This section describes container image specific compliance reports. For an overview of Trivy's Compliance feature, including working with custom compliance, check out the Compliance documentation.

Built in reports

The following reports are available out of the box:

Compliance Version Name for command More info
CIS Docker Community Edition Benchmark 1.1.0 docker-cis Link

Examples

Scan a container image configuration and generate a compliance summary report:

$ trivy image --compliance docker-cis [YOUR_IMAGE_NAME]

Note

The Issues column represent the total number of failed checks for this control.

Authentication

Please reference this page.

Options

Scan Image on a specific Architecture and OS

By default, Trivy loads an image on a "linux/amd64" machine. To customise this, pass a --platform argument in the format OS/Architecture for the image:

$ trivy image --platform=os/architecture [YOUR_IMAGE_NAME]

For example:

$ trivy image --platform=linux/arm alpine:3.16.1
Result
2022-10-25T21:00:50.972+0300    INFO    Vulnerability scanning is enabled
2022-10-25T21:00:50.972+0300    INFO    Secret scanning is enabled
2022-10-25T21:00:50.972+0300    INFO    If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2022-10-25T21:00:50.972+0300    INFO    Please see also https://aquasecurity.github.io/trivy/dev/docs/secret/scanning/#recommendation for faster secret detection
2022-10-25T21:00:56.190+0300    INFO    Detected OS: alpine
2022-10-25T21:00:56.190+0300    INFO    Detecting Alpine vulnerabilities...
2022-10-25T21:00:56.191+0300    INFO    Number of language-specific files: 0

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

┌─────────┬────────────────┬──────────┬───────────────────┬───────────────┬─────────────────────────────────────────────────────────────┐
│ Library │ Vulnerability  │ Severity │ Installed Version │ Fixed Version │                            Title                            │
├─────────┼────────────────┼──────────┼───────────────────┼───────────────┼─────────────────────────────────────────────────────────────┤
│ zlib    │ CVE-2022-37434 │ CRITICAL │ 1.2.12-r1         │ 1.2.12-r2     │ zlib: heap-based buffer over-read and overflow in inflate() │
│         │                │          │                   │               │ in inflate.c via a...                                       │
│         │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2022-37434                  │
└─────────┴────────────────┴──────────┴───────────────────┴───────────────┴─────────────────────────────────────────────────────────────┘

Configure Docker daemon socket to connect to.

You can configure Docker daemon socket with DOCKER_HOST or --docker-host.

$ trivy image --docker-host tcp://127.0.0.1:2375 YOUR_IMAGE

Configure Podman daemon socket to connect to.

You can configure Podman daemon socket with --podman-host.

$ trivy image --podman-host /run/user/1000/podman/podman.sock YOUR_IMAGE