← Back to DevBytes

Grype: Setup, Configuration, and Best Practices

What is Grype?

Grype is an open-source vulnerability scanner for container images, filesystems, and software development life cycle (SDLC) artifacts. Developed by Anchore, Grype is purpose-built to identify known security vulnerabilities in operating system packages and application dependencies. It works by comparing the contents of an image or directory against comprehensive vulnerability databases such as the National Vulnerability Database (NVD), GitHub Security Advisories, and distro-specific feeds.

Unlike some heavier scanners, Grype is designed to be fast, easy to integrate into CI/CD pipelines, and works directly with common formats like Docker images, OCI archives, SBOMs (Software Bill of Materials) in SPDX or CycloneDX format, and raw directories. It is written in Go and ships as a single static binary, making deployment straightforward across any environment.

Key Features at a Glance

Why Grype Matters

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

Modern applications are assembled from thousands of open-source components and base operating system packages. Every layer introduces potential vulnerabilities. A typical Docker image may inherit vulnerabilities from the base OS, from language-level dependencies, and from statically linked binaries. Grype gives developers and security teams a unified lens into all of these layers at once.

Grype matters because it shifts vulnerability detection left—into the development cycle—rather than waiting for a deployment audit. By scanning images before they reach production, teams can block vulnerable builds, patch dependencies proactively, and maintain compliance with frameworks such as PCI DSS, HIPAA, and SOC 2. Its speed and accuracy also make it suitable for real-time admission control in Kubernetes environments.

Installation and Setup

Grype ships as a single binary with no runtime dependencies. You can install it via package managers, download it from GitHub releases, or use the official Docker image. Here are the most common approaches:

Via Homebrew (macOS/Linux)

brew tap anchore/grype
brew install grype

Via curl (Linux/macOS)

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

This script fetches the latest release and places the binary in the specified directory. Verify the installation with:

grype version

Docker-based usage

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock anchore/grype:latest your-image:tag

Mounting the Docker socket allows Grype to pull and scan images directly. For air-gapped environments, you can pre-load the vulnerability database and pass it as a volume.

Configuration

Grype's behavior is controlled through a YAML configuration file, environment variables, and command-line flags. The default configuration file location is ~/.grype/config.yaml. You can generate a fresh configuration file to see all available options:

grype config --output yaml > ~/.grype/config.yaml

Configuration File Structure

A typical configuration file looks like this:

# ~/.grype/config.yaml
db:
  # Where the vulnerability database is stored
  dir: ~/.grype/db
  # Auto-update the database on each run
  auto-update: true
  # Validate database age (in days)
  max-db-age: 5

check:
  # Severity threshold: negligible, low, medium, high, critical
  fail-on-severity: high
  # Whether to show CVE details
  show-cve-detail: true

scan:
  # Exclude certain paths from scanning
  exclude-paths:
    - "/usr/share/doc/**"
    - "**/node_modules/**"
  # Only scan specific OS/distro types
  distro-preference:
    - debian
    - alpine

log:
  level: warn
  file: ~/.grype/logs/grype.log

Environment Variables

Every configuration key can be overridden with an environment variable using the prefix GRYPE_ and converting dots/colons to underscores:

# Set the database auto-update to false
export GRYPE_DB_AUTO_UPDATE=false

# Set the fail-on-severity threshold
export GRYPE_CHECK_FAIL_ON_SEVERITY=critical

# Specify a custom database path
export GRYPE_DB_DIR=/mnt/grype-db

Database Management

Grype relies on a local vulnerability database. On first run, it downloads the database automatically. You can also manage it explicitly:

# Download or update the database
grype db update

# Check database status
grype db status

# List available vulnerability sources
grype db list

For CI/CD pipelines, it's a best practice to cache the database or use a pre-seeded database volume to avoid repeated downloads.

How to Use Grype

Grype accepts several input types: container images, Docker archives, directories, and SBOM files. Here are practical examples for each scenario.

Scanning a Container Image

The most common use case: scan a Docker image directly from a registry or local cache.

# Scan a public image
grype nginx:1.25

# Scan with severity filtering
grype nginx:1.25 --fail-on high

# Output JSON for pipeline consumption
grype nginx:1.25 -o json > results.json

# Output as CycloneDX vulnerability report
grype nginx:1.25 -o cyclonedx-xml > results.xml

Scanning a Local Directory

Grype can scan a filesystem path directly, which is useful for scanning build artifacts before containerization:

grype dir:/path/to/your/project

# Scan the current directory
grype dir:.

Scanning an SBOM File

If you have already generated an SBOM (for example, with Syft), Grype can consume it directly:

# Generate an SBOM with Syft
syft nginx:1.25 -o spdx-json > nginx.spdx.json

# Scan the SBOM with Grype
grype sbom:./nginx.spdx.json

This decouples inventory gathering from vulnerability scanning—ideal for staged pipelines where SBOM generation happens once and scanning happens multiple times against updated vulnerability data.

Using Grype with Syft in a Pipeline

A powerful pattern combines Syft and Grype in a single pipeline step:

# Pipe Syft output directly into Grype
syft your-image:latest -o json | grype

# Or capture both SBOM and vulnerabilities
syft your-image:latest -o spdx-json > sbom.json
grype sbom:./sbom.json -o json > vulnerabilities.json

Ignoring and Accepting Vulnerabilities

Not every vulnerability is exploitable in your context. Grype provides mechanisms to suppress specific findings.

Inline ignores via a YAML file:

# .grype/ignores.yaml
ignore:
  - vulnerability: CVE-2023-12345
    package: libssl
    reason: "Not exploitable in our configuration—we use TLS 1.3 exclusively"
    target: nginx:1.25
  - vulnerability: GHSA-xxxx-xxxx-xxxx
    package: lodash
    reason: "Only used in dev builds, not present in production image"

Apply it with:

grype nginx:1.25 --ignore-file .grype/ignores.yaml

Output Formats and Integration

Grype supports multiple output formats that plug directly into different ecosystems:

# Table format (default, human-readable)
grype alpine:latest

# JSON format
grype alpine:latest -o json

# CycloneDX XML/JSON
grype alpine:latest -o cyclonedx-json
grype alpine:latest -o cyclonedx-xml

# SARIF for GitHub Code Scanning integration
grype alpine:latest -o sarif > grype-results.sarif

For GitHub Actions, you can upload SARIF results directly:

name: Container Vulnerability Scan
on: [push]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Scan image with Grype
        run: |
          grype your-image:latest -o sarif > grype-results.sarif
      - name: Upload SARIF to GitHub
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: grype-results.sarif

Best Practices

1. Keep the Vulnerability Database Fresh

The database is the brain of Grype. An outdated database misses newly disclosed vulnerabilities. Configure automatic updates and set a maximum database age that aligns with your risk tolerance:

# In config.yaml
db:
  auto-update: true
  max-db-age: 1  # Fail if database is older than 1 day

In air-gapped environments, set up a cron job to pull the database on a schedule and distribute it to scanning nodes.

2. Fail Builds on Severity Thresholds

Integrate Grype into CI/CD with a strict pass/fail policy. Use --fail-on to break the build when vulnerabilities exceed a threshold:

grype your-image:latest --fail-on high

This returns a non-zero exit code when any vulnerability at "high" or "critical" severity is found. Combine with --fail-on-severity in the config file for consistent enforcement across teams.

3. Generate and Store SBOMs as Build Artifacts

Rather than scanning images directly every time, generate an SBOM with Syft at build time and store it as an immutable artifact. Then scan the SBOM with Grype. This decouples inventory from vulnerability analysis and lets you re-scan the same SBOM as new CVEs emerge:

# Build step
syft your-image:latest -o spdx-json > sbom.spdx.json
# Archive sbom.spdx.json as a build artifact

# Later, scan the SBOM
grype sbom:sbom.spdx.json -o json > vuln-report.json

4. Maintain a Curated Ignore File

Not all vulnerabilities are relevant. Maintain a version-controlled ignore file that documents why specific vulnerabilities are suppressed. Require a reason for each entry and review the file regularly:

ignore:
  - vulnerability: CVE-2024-XXXX
    package: openssl
    reason: "We pin OpenSSL to a patched version via overlay"
    reviewed-by: "security-team"
    review-date: "2025-01-15"

Treat the ignore file like code—review it in pull requests and expire entries after a set period.

5. Use Grype in Admission Controllers

For Kubernetes, integrate Grype into admission webhooks to block deployment of vulnerable images. Tools like Anchore Enterprise, OPA, or custom webhooks can call Grype and reject pods that exceed your severity policy. A minimal example using a validating webhook:

# Extract image digest from the admission request
# Run Grype against the image
grype "${IMAGE_DIGEST}" --fail-on critical
# If exit code != 0, deny the admission request

6. Combine with Policy-as-Code

Grype's JSON output can be consumed by policy engines such as OPA (Open Policy Agent) or Kyverno. Write Rego policies that encode organizational rules beyond simple severity thresholds—for example, blocking images older than 30 days or requiring vendor-specific patches:

# Example OPA policy snippet
deny[msg] {
  vuln := input.matches[_]
  vuln.vulnerability.severity == "Critical"
  not ignored_vulns[vuln.vulnerability.id]
  msg := sprintf("Critical vulnerability %s found in %s", [vuln.vulnerability.id, vuln.artifact.name])
}

7. Leverage Distro-Specific Scanning

Grype automatically detects the Linux distribution in a container image and uses the appropriate vulnerability feed. For multi-stage builds or distroless images, ensure the base OS layers are scanned. If Grype misidentifies the distro, you can hint it:

grype your-image:latest --distro debian:12

8. Parallelize and Cache in CI/CD

Database download is often the slowest part of a Grype scan. Cache the database directory (~/.grype/db) across CI runs using build cache mechanisms (e.g., GitHub Actions cache, CircleCI save_cache). For monorepos with many images, run Grype scans in parallel and aggregate results.

# GitHub Actions cache example
- name: Cache Grype DB
  uses: actions/cache@v4
  with:
    path: ~/.grype/db
    key: grype-db-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}

9. Tag Images with Scan Results

In production pipelines, tag container images with metadata about their vulnerability status. This creates an auditable chain and prevents operators from accidentally deploying unscanned images:

# After a successful scan
docker tag your-image:latest your-image:scanned-high-pass
# Push both tags
docker push your-image:latest
docker push your-image:scanned-high-pass

10. Regularly Review and Rotate Policies

Vulnerability management is not a one-time setup. Schedule quarterly reviews of your Grype configuration: revisit severity thresholds, prune stale ignore entries, update database freshness windows, and align policies with evolving compliance requirements. Automate reminders with calendar tickets or dashboard metrics that show policy effectiveness over time.

Conclusion

Grype is a fast, flexible, and highly integrable vulnerability scanner that fits naturally into modern containerized development workflows. From the developer's local environment to the CI/CD pipeline and all the way to Kubernetes admission control, Grype provides consistent, actionable vulnerability intelligence. By following the setup patterns and best practices outlined in this tutorial—keeping the database fresh, failing builds on defined severity thresholds, maintaining curated ignore files, generating and storing SBOMs, and integrating with policy engines—you can build a robust vulnerability management program that catches risks early, reduces alert fatigue, and keeps production deployments secure. The key is to treat vulnerability scanning not as a checkbox activity but as an ongoing, policy-driven practice embedded throughout the software delivery lifecycle.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles