Scan Container Images for Vulnerabilities with Grype

Containerized application and service deployments have a lot of moving parts, which can equate to a significantly large attack plane.
That’s why it’s absolutely crucial that you start on the right foot. To do that, you must be certain the images you base your containers are free from vulnerabilities. But how do you do that? There are plenty of tools available, but one of them stands out (at least to me) as considerably easier to use than most others.
That tool is Grype.
Grype, an open source package managed by security company Anchore, is a vulnerability scanner for both images and filesystems. It has taken the place of the now-deprecated Anchore Inline Scanning script (which reaches end-of-life on Jan 10, 2022). The Anchor vulnerability database will no longer be kept up to date and new images will no longer be published. Because of that, it’s time to move forward with Grype.
As I said, Grype is quite simple to use and can scan for vulnerabilities of packages within the following images:
- Alpine
- Amazon Linux
- BusyBox
- CentOS
- Debian
- Distroless
- Oracle Linux
- Red Hat (RHEL)
- Ubuntu
But Grype isn’t limited to only those official images. Any image based on the above can be scanned. I’ve used Grype to successfully scan all sorts of images (such as NGINX, MySQL, and more). Grype is also perfectly at home finding vulnerabilities for language-specific packages, such as these:
- Ruby (Gems)
- Java (JAR, WAR, EAR, JPI, HPI)
- JavaScript (NPM, Yarn)
- Python (Egg, Wheel, Poetry, requirements.txt/setup.py files)
I want to walk you through the process of installing Grype and then using it to scan an image. I’ll demonstrate installing Grype on Linux (Pop!_OS) and macOS Monterey. I will assume you already have Docker, Podman, or your container runtime engine of choice up and running.
And with that, let’s get Grype’ing.
Installing Grype on Linux
Log into your Linux machine and open a terminal window. At the terminal, issue the command:
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sudo sh -s -- -b /usr/local/bin
Once the installation is complete, you can verify it with the command:
grype -h
The above command will print out the Grype help file.
Installing Grype on MacOS
In order to install Grype on macOS, you must use Homebrew. To install homebrew, open a terminal window on your Apple device and issue the command:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
The installation will take some time, so either sit back and watch the output fly by or take care of another task and return later.
Once Homebrew is installed, you first must “tap” Grype for installation with the command:
brew tap anchore/grype
When that completes, install Grype with:
brew install grype
So far so good. Grype is up and running and ready for scans on either Linux or macOS. Let’s do just that.
Using Grype to Scan Images
The basic Grype usage is:
grype IMAGE
Where IMAGE is the name of the image.
For example, I can scan the NGINX image with the command:
grype nginx:latest
You might have noticed that I included the tag with the image name. This is necessary if you have more than one version of an image pulled. For example, you might have the official MySQL image pulled (mysql:latest) as well as the ubuntu/mysql:8.0-22.04_beta image. If you do not specify the tag, and you have more than one version, grype will error out.
After running the scan on the image, Grype will report any vulnerability it finds (Figure 1).
Figure 1

Grype has found several vulnerabilities (some of them marked as High) in the official NGINX image.
Each package scanned within an image will be listed and the output includes:
- NAME – the name of the package.
- INSTALLED – the version number installed in the image.
- FIXED-IN – the version in which a vulnerability has been fixed.
- TYPE – the type of package
- VULNERABILITY – the CVE listing of each vulnerability.
- SEVERITY – the severity of each vulnerability.
You’ll want to pay very close attention to both the SEVERITY and VULNERABILITY listing for each package.
That’s a fairly basic scan. If you want to include packages from all image layers (no matter if it’s present in the final image), you can issue the command like so:
grype nginx:latest --scope all-layers
The difference? By scanning the nginx:latest image, Grype found 143 cataloged packages and 138 vulnerabilities. When running with the scope options, Grype found 239 packages and the same number of vulnerabilities. In the scope scan, Grype checks packages that are visible to the container, thus the fewer number of packages.
If your image is part of a project, you can use Grype to scan the entire project. Say, for instance, your project is located in ~/myproject. To scan that project with Grype, use a command like this:
grype dir:~/myproject/
Grype will dive into the directory and scan every relevant package and report any vulnerabilities found.
Conclusion
If you’re looking for what might be the easiest image vulnerability scanning tool on the market, Grype might well be just the ticket. This command-line application is not only simple to use but a reliable way of discerning if those images you plan on working with contain vulnerabilities and, if they do, how severe they are. If you’re serious about your container security, it all begins (but doesn’t end) with the images your deployments are based on.