Understanding Grype results
TL;DR
- Default table output shows package, vulnerability, severity, and fix info
- Match types in JSON output indicate reliability:
exact-direct-matchandexact-indirect-matchare high confidence,cpe-matchrequires verification - Use
--by-cveto normalize vulnerability IDs to CVE format - Filter results with
jqfor analysis by match type, severity, or data source
This guide explains how to read and interpret Grype’s vulnerability scan output. You’ll learn what different match types mean, how to assess result reliability, and how to filter results based on confidence levels.
Output formats
Grype supports several output formats for scan results:
- Table (default) - Human-readable columnar output for terminal viewing
- JSON - Complete structured data with all match details
- SARIF - Standard format for tool integration and CI/CD pipelines
- Template - Custom output using Go templates
This guide focuses on table and JSON formats, which you’ll use most often for understanding scan results.
Reading table output
The table format is Grype’s default output. When you run grype <image>, you see a table displaying one row per
unique vulnerability match, with deduplication of identical rows.
Table columns
The table displays eight standard columns, with an optional ninth column for annotations:
- NAME - The package name
- INSTALLED - The version of the package
- FIXED-IN - The version that fixes the vulnerability (shows
(won't fix)if the vendor won’t fix it, or empty if no fix is available). See Filter by fix availability to filter results based on fix states - TYPE - Package type (apk, deb, rpm, npm, python, java-archive, etc.)
- VULNERABILITY - The vulnerability identifier (see below)
- SEVERITY - Vulnerability severity rating (Critical, High, Medium, Low, Negligible, Unknown)
- EPSS - Exploit Prediction Scoring System score and percentile showing the probability of exploitation
- RISK - Calculated risk score combining CVSS, EPSS, and other severity metrics into a single numeric value (0.0 to 10.0)
- Annotations (conditional) - Additional context like KEV (Known Exploited Vulnerability), suppressed status, or distribution version when scanning multi-distro images
Here’s what a typical scan looks like:
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY EPSS RISK
log4j-core 2.4.0 2.12.2 java-archive CVE-2021-44228 Critical 94.4% (99th) 100.0 (kev)
log4j-core 2.4.0 2.12.2 java-archive CVE-2021-45046 Critical 94.3% (99th) 99.0 (kev)
apk-tools 2.10.6-r0 2.10.7-r0 apk CVE-2021-36159 Critical 12% (85th) 8.5
libcrypto1.1 1.1.1k-r0 apk CVE-2021-3711 Critical 9% (78th) 9.1
libcrypto1.1 1.1.1k-r0 (won't fix) apk CVE-2021-3712 High 5% (62nd) 7.2
The Annotations column appears conditionally to provide additional context:
- KEV or (kev) - Indicates the vulnerability is in CISA’s Known Exploited Vulnerabilities catalog
- suppressed or suppressed by VEX - Shown when using
--show-suppressedflag (see View filtered results) - Distribution version (e.g.,
ubuntu:20.04) - Shown when scan results include matches from multiple different distributions
Understanding vulnerability IDs
The VULNERABILITY column displays different types of identifiers depending on the data source:
- CVE IDs (e.g.,
CVE-2024-1234) - Common Vulnerabilities and Exposures identifiers used by most Linux distributions (Alpine, Debian, Ubuntu, RHEL, SUSE) and the NVD - GHSA IDs (e.g.,
GHSA-xxxx-xxxx-xxxx) - GitHub Security Advisory identifiers for language ecosystem packages - ALAS IDs (e.g.,
ALAS-2023-1234) - Amazon Linux Security Advisory identifiers - ELSA IDs (e.g.,
ELSA-2023-12205) - Oracle Enterprise Linux Security Advisory identifiers
By default, Grype displays the vulnerability ID from the original data source. For example, an Alpine package might show CVE-2024-1234
while a GitHub Advisory for the same issue shows GHSA-abcd-1234-efgh. Use the --by-cve flag to normalize results to CVE identifiers:
grype <image> --by-cve
This flag replaces non-CVE vulnerability IDs with their related CVE ID when available, uses CVE metadata instead of the original advisory metadata, and makes it easier to correlate vulnerabilities across different data sources.
Compare the two approaches:
# Default output - shows GitHub Advisory ID
$ grype node:18
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY
lodash 4.17.20 4.17.21 npm GHSA-35jh-r3h4-6jhm High
# With --by-cve - converts to CVE
$ grype node:18 --by-cve
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY
lodash 4.17.20 4.17.21 npm CVE-2021-23337 High
Sorting results
By default, Grype sorts vulnerability results by risk score, which combines multiple factors to help you prioritize remediation efforts. Understanding how sorting works and when to use alternative methods helps you build effective security workflows.
Why risk-based sorting works best
The default risk score takes a holistic approach by combining:
- Threat (likelihood of exploitation) - Based on EPSS (Exploit Prediction Scoring System) scores or presence in CISA’s Known Exploited Vulnerabilities (KEV) catalog
- Impact (potential damage) - Based on CVSS scores and severity ratings from multiple sources
- Context (exploitation evidence) - Additional weight for vulnerabilities with known ransomware campaigns
This multi-factor approach aligns with security best practices recommended by the EPSS project, which emphasizes that “CVSS is a useful tool for capturing the fundamental properties of a vulnerability, but it needs to be used in combination with data-driven threat information, like EPSS.”
Risk-based sorting helps you focus on vulnerabilities that are both likely to be exploited AND have significant business impact, optimizing your remediation efficiency.
Why single-metric sorting can be misleading
While Grype offers several sorting options via the --sort-by flag, using single metrics can lead to inefficient prioritization:
Severity-only sorting (--sort-by severity) focuses solely on potential impact:
- You may waste effort patching Critical severity vulnerabilities that are unlikely to ever be exploited in the wild
- No consideration for whether attackers are actively targeting the vulnerability
- Ignores real-world threat intelligence
EPSS-only sorting (--sort-by epss) focuses solely on exploitation likelihood:
- You may prioritize vulnerabilities with high exploitation probability but low business impact
- EPSS is not a risk score – it only addresses the threat component, not the complete risk picture
- Missing context like asset criticality, network exposure, or available compensating controls
The EPSS documentation explicitly states that EPSS scores should be combined with severity information to make informed prioritization decisions, which is exactly what Grype’s risk score does.
Understanding EPSS in Grype
EPSS (Exploit Prediction Scoring System) is a data-driven scoring model that estimates the probability a vulnerability will be exploited in the next 30 days.
Grype displays EPSS data in the table output showing both the raw score and percentile, such as 94.4% (99th), which means:
- 94.4% - The raw EPSS score indicating a 94.4% probability of exploitation within 30 days
- 99th - The percentile rank, meaning this score is higher than 99% of all EPSS scores
EPSS percentiles help normalize the heavily skewed distribution of EPSS scores, making it easier to set thresholds. For example, a vulnerability in the 90th percentile is more concerning than one in the 50th percentile, even if the raw likelihood values appear to be similar.
Grype incorporates EPSS as the threat component of its risk calculation. When a vulnerability appears in the KEV catalog, Grype automatically treats it as maximum threat (overriding EPSS) since observed exploitation is more significant than predicted exploitation.
For more details on EPSS methodology and interpretation, see the EPSS model documentation.
When to use alternative sorting methods
While risk-based sorting is recommended for most remediation workflows, alternative sorting methods serve specific use cases:
Sort by KEV status (--sort-by kev):
- When you need to comply with regulatory requirements like CISA BOD 22-01
- For incident response scenarios focusing on actively exploited vulnerabilities
Sort by severity (--sort-by severity):
- When organizational SLAs or compliance frameworks specify severity-based remediation timeframes (e.g., “patch all Critical within 7 days”)
Sort by EPSS (--sort-by epss):
- For threat landscape analysis and security research
Sort by package (--sort-by package):
- When organizing remediation work by team ownership (different teams maintain different packages)
- For coordinating updates across multiple instances of the same package
Sort by vulnerability ID (--sort-by vulnerability):
- When tracking specific CVE campaigns across your environment
- For correlating findings with external threat intelligence reports
For most security and remediation workflows, stick with the default risk-based sorting. It provides the best balance of threat intelligence and impact assessment to help you prioritize effectively.
Next steps
Continue the guide
Next: Learn how to work with the JSON results.Additional resources:
- Filter results: Use result filtering for severity thresholds and ignore rules
- Supported ecosystems: Understand data source selection for different package types
- Configuration: See Grype configuration reference for customizing behavior