Quick Links

Grype is an open-source vulnerability scanner that finds weaknesses within container images and filesystem directories. Grype is developed by Anchore but works as a standalone binary that's easier to get to grips with than the Anchore Engine.

Known vulnerabilities make their way into your software via outdated operating system packages, compromised programming language dependencies, and insecure base images. Actively scanning your artifacts keeps you informed of issues before malicious actors find them. Here's how to use Grype to find problems in your code and containers.

Installing Grype

Grype is distributed as a pre-compiled binary in

        deb
    

,

        rpm
    

, Linux source, and Mac formats. You can grab the latest release from GitHub and install it with your system's package manager or by copying the binary to a location in your path. Alternatively, use the installation script to automate the process:

        curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
    

Check your binary's working by running the grype command. Documentation on the available commands will be displayed.

Basic Scans

In its simplest form, Grype takes a single argument that specifies the container image or filesystem path to scan. To scan an image, supply a valid registry tag. Grype will use available Docker credentials to pull images from Docker Hub and private registries.

        grype alpine:latest
    

You can also scan an image archive that's been exported from Docker:

        grype saved-image.tar
    

Grype will download its vulnerability database the first time it's run. This currently weighs in at about 90MB. Once the database is available, Grype will pull the Docker image, catalogue the software inside it, and parse known vulnerabilities present in the database.

Screnshot of a Grype container scan

The results are displayed in a table within your terminal. Each vulnerability includes its CVE ID, the name of the affected package, and its severity level. When the problem's been patched in a later release, you'll see that update's version number in the FIXED-IN column. This helps you establish whether a vulnerability can be readily addressed with a simple package manager update.

Grype can work with packages for all the most popular Linux distributions. It also supports Ruby Gems, NPM and Yarn packages, Python Eggs, Wheels, and Poetry dependencies, and Java modules in JAR, WAR, EAR, JPI, and HPI formats.

Scanning Filesystems

Grype can scan filesystem paths on your machine. This lets you discover vulnerabilities in source code repositories before you've built an image. To use this feature, specify a directory path with the dir: scheme:

        grype dir:/example-dir
    

Grype will look for compatible files nested under the given directory root. Each found file will be indexed and scanned for vulnerabilities.

Screnshot of a Grype filesystem scan

Filesystem scans surface the same types of vulnerability as container image scans. The scan might take a couple of minutes to complete if you're working with a large directory tree.

Filtering Vulnerabilities

Two filtering flags are supported to scope the report to just the vulnerabilities or resolution options you're interested in:

  • --only-fixed - Only show vulnerabilities that have been patched in a later release of the affected package.
  • --fail-on high - Exit immediately with an error code when a high-level vulnerability is found. You can substitute any supported error level (critical, high, medium, or low) instead of high.

Ignoring Vulnerabilities

Vulnerabilities can be ignored to hide false positives or issues you've decided not to address, perhaps because they're not relevant to your use of the package.

To ignore a vulnerability, you need to create a custom Grype config file in YAML format. Add the vulnerability's CVE under the top-level ignore field:

ignore:

- vulnerability: CVE-2021-12345

Other fields are supported too, such as this variant to ignore all issues stemming from NPM packages:

ignore:

- package:

type: npm

Save your config file to .grype.yaml or .grype/config.yaml in your working directory. It'll be used automatically next time you run a Grype scan. The global config file ~/.grype.yaml is also supported. The file in your working directory will be merged with the global one at runtime.

Vulnerabilities will not affect Grype's exit code if they're ignored. The JSON report will move them to a separate ignoredMatches field while terminal table reports exclude them altogether. If you ignore a vulnerability, remember to document why it's been accepted so every contributor understands the risk.

Using SBOMs

Grype can work with SBOMs generated by Syft, another of Anchore's projects. Syft indexes your container images to produce a list of the dependencies they contain.

Use Syft to create an SBOM for your image in JSON format:

        syft alpine:latest -o json > alpine-sbom.json
    

Then run a Grype scan using the SBOM:

        grype sbom:/alpine-sbom.json
    

Grype will inspect the referenced image for new vulnerabilities arising from its bill of materials. Keep using Grype with your SBOM to monitor for emerging issues in image dependencies that you've already audited and indexed.

Customizing Grype Output

Grype provides four different output formatters which you can switch between using the -o CLI flag:

  • table - The default human-readable table for in-terminal consumption.
  • json - A JSON-formatted report containing much more comprehensive information about each vulnerability, as well as details of the Grype database used for scanning. JSON files are suitable for long-term archiving and comparison, or use as CI build artifacts.
  • cyclonedx - A CycloneDX-compatible report in XML format which is ready to feed into other tools supporting SBOMs and vulnerability lists.
  • template - This advanced formatter lets you produce your own reports in arbitrary formats.

The template formatter accepts a Go template that will be used to render the report output. To use this formatter, don't specify it by name - instead, pass the path to a file containing your Go template:

        grype alpine:latest -o output-template.tmpl
    

The template should use the Go templating syntax to reference variables that Grype provides. You can construct any kind of file format you need, such as an HTML page, a Markdown file, or a custom JSON structure. The Grype docs include an example of producing a CSV file from the available variables.

Vulnerability Database

The vulnerability database stores details of all the vulnerabilities known to Grype. Once it's been downloaded, the cached version will be reused until an update is available. Manual interactions with the database aren't usually necessary.

In some situations you might need to force a database download. This could be because you're setting up an air-gapped server in advance of running a scan. Use the grype db check and grype db update commands to check for and download a newer version of the database.

Once the database is available, scans will work while your system's offline. You can disable Grype's automatic database update checks by setting the GRYPE_DB_AUTO_UPDATE environment variable to false in your shell.

Summary

Grype alerts you to vulnerabilities inside your containers and on your filesystem. As a standalone CLI binary, it's easier to get started with than a full Anchore installation.

If you're wondering which you should choose, Anchore's value lies in its extensibility and advanced configuration options. With Anchore Engine you can define your own policy sets based on gates, triggers, and actions. These let you precisely tailor your scans to your specific environment. Grype provides a more streamlined experience when you just want a list of known vulnerabilities in your image.

Whichever you choose, adopting some form of active vulnerability scanning will keep you informed of weaknesses in your software supply chain. For a fully integrated approach, use Grype as part of your CI pipeline so you're alerted to new vulnerabilities as code is committed.