Vulnerabilities are everywhere. Application developers use frameworks and libraries to solve business requirements. An operating system executes applications and their dependencies, and vulnerabilities could exist in each of those layers.

Obviously, as application developers, we fix potential vulnerabilities in our code-bases. However, fixing critical vulnerabilities in the Linux distribution our applications rely on, is probably not what we are responsible for. Often, it is more important to know which vulnerabilities exist and how we can fix them.

Checking Docker images against well-known vulnerabilities and providing a classified list of them in combination with instructions on fixing the vulnerabilities is what tools like Snyk offer. Docker CLI provides seamless integration with Snyk, which allows us to check our Docker images for vulnerabilities locally and receive a detailed scanning report.

Scanning Docker images for vulnerabilities

Invoke docker scan, followed by the name and tag of the desired Docker image, to scan a Docker images. For example, create a new Docker image using a - quite dated - Node.js base image as shown here:

FROM node:7-alpine

Use docker build . -t sample:0.0.1 to create Docker image and start a vulnerability scan for the image by executing docker scan:

# scan Docker image sample:0.0.1 for vulnerabilities
docker scan sample:0.0.1
Testing sample:0.0.1...

✗ Medium severity vulnerability found in openssl/libcrypto1.0
  Description: Use of a Broken or Risky Cryptographic Algorithm
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-373420
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2q-r0

✗ Medium severity vulnerability found in openssl/libcrypto1.0
  Description: Uncontrolled Recursion
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-373830
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2o-r0

✗ Medium severity vulnerability found in openssl/libcrypto1.0
  Description: Out-of-Bounds
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-373939
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2m-r0

✗ Medium severity vulnerability found in openssl/libcrypto1.0
  Description: Information Exposure
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-374112
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2n-r0

✗ Medium severity vulnerability found in openssl/libcrypto1.0
  Description: Information Exposure
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-374229
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2m-r0

✗ Medium severity vulnerability found in openssl/libcrypto1.0
  Description: Use of a Broken or Risky Cryptographic Algorithm
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-374280
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2o-r2

✗ Medium severity vulnerability found in openssl/libcrypto1.0
  Description: Information Exposure
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-374450
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2q-r0

✗ Medium severity vulnerability found in openssl/libcrypto1.0
  Description: Out-of-bounds Read
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-374514
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2n-r0

✗ Medium severity vulnerability found in openssl/libcrypto1.0
  Description: Improper Input Validation
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-374732
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2o-r0

✗ High severity vulnerability found in openssl/libcrypto1.0
  Description: Key Management Errors
  Info: https://snyk.io/vuln/SNYK-ALPINE34-OPENSSL-374005
  Introduced through: openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, apk-tools/apk-tools@2.6.9-r0
  From: openssl/libcrypto1.0@1.0.2k-r0
  From: openssl/libssl1.0@1.0.2k-r0 > openssl/libcrypto1.0@1.0.2k-r0
  From: apk-tools/apk-tools@2.6.9-r0 > openssl/libcrypto1.0@1.0.2k-r0
  and 2 more...
  Fixed in: 1.0.2o-r1

✗ High severity vulnerability found in musl/musl
  Description: Out-of-Bounds
  Info: https://snyk.io/vuln/SNYK-ALPINE34-MUSL-291884
  Introduced through: musl/musl@1.1.14-r15, busybox/busybox@1.24.2-r13, alpine-baselayout/alpine-baselayout@3.0.3-r0, openssl/libcrypto1.0@1.0.2k-r0, openssl/libssl1.0@1.0.2k-r0, zlib/zlib@1.2.11-r0, apk-tools/apk-tools@2.6.9-r0, gcc/libgcc@5.3.0-r0, musl/musl-utils@1.1.14-r15, pax-utils/scanelf@1.1.6-r0, libc-dev/libc-utils@0.7-r0
  From: musl/musl@1.1.14-r15
  From: busybox/busybox@1.24.2-r13 > musl/musl@1.1.14-r15
  From: alpine-baselayout/alpine-baselayout@3.0.3-r0 > musl/musl@1.1.14-r15
  and 10 more...
  Fixed in: 1.1.14-r16

Organization:      ****
Package manager:   apk
Project name:      docker-image|sample
Docker image:      sample:0.0.1
Platform:          linux/amd64

Tested 13 dependencies for known vulnerabilities, found 11 vulnerabilities.

Alpine 3.4.6 is no longer supported by the Alpine maintainers. Vulnerability detection may be affected by a lack of security updates.

For more free scans that keep your images secure, sign up to Snyk at https://dockr.ly/3ePqVcp

As the report shows, the scanner found 11 vulnerabilities when testing the Docker image. The report provides detailed information and instructions on how to fix every vulnerability. Additionally, Snyk points out that version 3.4.6 of Alpine Linux is no longer maintained. So updating the Docker could perhaps be a good start.

FROM node:15-alpine

Create sample:0.0.2 by invoking docker build . -t sample:0.0.2. Once the build process has finished, you can start another vulnerability scan.

docker scan sample:0.0.2
Testing sample:0.0.2...

✗ Low severity vulnerability found in musl/musl
  Description: CVE-2020-28928
  Info: https://snyk.io/vuln/SNYK-ALPINE311-MUSL-1042763
  Introduced through: musl/musl@1.1.24-r2, busybox/busybox@1.31.1-r9, alpine-baselayout/alpine-baselayout@3.2.0-r3, openssl/libcrypto1.1@1.1.1g-r0, openssl/libssl1.1@1.1.1g-r0, zlib/zlib@1.2.11-r3, apk-tools/apk-tools@2.10.5-r0, libtls-standalone/libtls-standalone@2.9.1-r0, busybox/ssl_client@1.31.1-r9, gcc/libgcc@9.3.0-r0, musl/musl-utils@1.1.24-r2, pax-utils/scanelf@1.2.4-r0, libc-dev/libc-utils@0.7.2-r0
  From: musl/musl@1.1.24-r2
  From: busybox/busybox@1.31.1-r9 > musl/musl@1.1.24-r2
  From: alpine-baselayout/alpine-baselayout@3.2.0-r3 > musl/musl@1.1.24-r2
  and 12 more...
  Fixed in: 1.1.24-r3

Organization:      ***
Package manager:   apk
Project name:      docker-image|sample
Docker image:      sample:0.0.2
Platform:          linux/amd64

Tested 16 dependencies for known issues, found 1 issue.

Updating to the latest base-image eliminated ten vulnerabilities, which means that the Docker image has just one vulnerability left.

That’s awesome.

Update msul to the latest version to remove the last remaining vulnerability as the report suggests. Modify the Dockerfile and upgrade musl using the package manager of Alpine Linux (apk).

FROM node:15-alpine
RUN apk upgrade musl

Again, build a new tag with docker build . -t sample:0.0.3 and issue another vulnerability scan:

docker scan sample:0.0.3
Testing sample:0.0.3...

Organization:      ***
Package manager:   apk
Project name:      docker-image|sample
Docker image:      sample:0.0.3
Platform:          linux/amd64

✓ Tested 16 dependencies for known issues, no vulnerable paths found.

Boom! No more vulnerabilities.

Dockerfile recommendations - Get deep insights from Snyk

Snyk provides even more details when scanning container images for vulnerabilities. It can

  • recommend more recent and smaller base images
  • highlight instructions of your Dockerfile that actually cause vulnerabilities

You get all of these, by adding a single, additional argument to docker scan pointing to the Dockerfile, used to create the desired Docker image.

docker scan sample:0.0.3 --file Dockerfile

Obviously, the Dockerfile shown in this article is fairly simple and all vulnerabilities are already fixed. However, this feature is really handy when you face real-world Dockerfiles.

Snyk - 10 vulnerability scans per month without authentication

Without any further configuration, you can execute ten (10) scans per month using docker scan and Snyk. Once you reach this limit, you have to login with a Snyk account, to continue scanning Docker images locally.

# login with Snyk account
docker scan --login

Once logged in, you can continue scanning images locally. Snyk offers a free tier that is feasible for personal usage. For further details on Snyk licensing, consult the official Snyk website.

Image Scanning quirks on Windows and WSL2

No container story without limitations for the Windows fan base.

When running docker scan in WSL 2, the service is not able to scan images based on Alpine Linux.

Additionally, if you are running Debian or OpenSUSE as distribution in WSL 2, you have to login against Snyk using the --token argument. Different authentication flows will not work.

Conclusion

Scanning Docker images for well-known vulnerabilities is definitely a task that your container registry (eg. Azure Container Registry) should take care of. If you haven’t heard of Azure Container Registry (ACR) yet, check out the Azure Container Registry Unleashed series.

However, by using docker scan and Snyk locally, you can verify and eliminate vulnerabilities in your Docker images before pushing them to an internal or even a public registry. In my opinion, developers should consider scanning Docker images in the inner loop using docker scan to increase both: quality and robustness.