Trivy Basics and How to Read Scan Results
Published: September 10, 2026
Introduction
Trivy is a tool for checking container images for vulnerabilities. To use its results, you need to understand what was scanned and what each field means, as well as the number and severity of the findings.
This article explains Trivy's basics, scan targets, how to read JSON output, and considerations when using the results for vulnerability management.
What is Trivy?
Trivy is an open-source security scanner developed by Aqua Security. In addition to known vulnerabilities, it can detect misconfigurations and credentials embedded in files.
| Feature | What it checks or produces |
|---|---|
| Vulnerability scanning | Known vulnerabilities in OS packages and dependencies |
| Misconfiguration scanning | Configuration issues in Dockerfiles, Kubernetes, Terraform, and other files |
| Secret detection | Content that appears to contain sensitive information, such as API keys |
| License scanning | Package license information |
| SBOM generation | An inventory of detected software components |
Not every feature is enabled for every target. Coverage depends on the combination of target, scanners, and options.1
Vulnerability detection works by identifying software and its version, then matching it against the corresponding vulnerability information. Trivy does not send attacks to an application to test whether exploitation succeeds.
A detected vulnerability and a successful attack in your environment are therefore different things.
Trivy scan targets
Common scan targets and commands include:
| Target | Example command | Main contents examined |
|---|---|---|
| Container image | trivy image nginx:1.20 |
OS packages, libraries, files, and other image contents |
| Local directory | trivy fs ./my-project |
Dependency manifests, configuration files, and other files in the specified location |
| Git repository | trivy repo https://github.com/owner/repo |
Dependency manifests, configuration files, and other repository contents |
The repository URL is a placeholder. Replace it with the URL of the repository you want to scan.
trivy fs also accepts a single file. You can specify a supported lock file
directly to check its dependencies for vulnerabilities.2
trivy repo scans source repositories. The documentation describes support
for files such as lock files, but excludes build artifacts such as JARs and
binaries.3
Why file and image scans produce different results
Consider a Node.js application repository containing a package-lock.json
file and a Dockerfile.
- A repository scan examines dependencies recorded in files such as lock files.
- An image scan examines the OS packages and libraries actually present in the built image.
- A base image named in a Dockerfile's
FROMinstruction is not automatically scanned by scanning the repository.
Development files and the artifacts you distribute and run provide different information. Neither type of scan necessarily produces more findings than the other.
Development dependencies are not necessarily scanned just because they appear in a lock file. Check support for the language and the settings for including development dependencies.
Shared output formats
fs, repo, and image support common output formats, including tables and
JSON.
The basic JSON structure and main vulnerability fields are shared, but some fields, such as image IDs and layer information, are specific to the target. Not every field is always present.4
Installing Trivy
Follow the official installation instructions to install Trivy. Then check its version:
Scanning an image and producing JSON output
The basic command for scanning an image is:
Trivy downloads its vulnerability database when needed, including on the first run. Installing Trivy and updating vulnerability information are separate operations. The same Trivy version can produce different results depending on the database it uses.5
To save the results as JSON, specify the output format and file name:
To explicitly request the package inventory as well, use:
An existing output file with the same name is overwritten. Use a different name if you want to keep earlier results.4
How to read scan results
This section uses counts and JSON excerpts from a scan of nginx:1.20
performed with Trivy 0.71.2 on September 9, 2026.
The version you install and the results of a new scan may differ from this example.
Scan target and counts
| Item | Recorded value |
|---|---|
| Trivy | 0.71.2 |
| Report creation time | September 9, 2026, 10:45 JST |
| Target | nginx:1.20 |
| Detected OS | Debian 11.3 |
| nginx package version | 1.20.2 |
| Packages in the inventory | 142 |
| Vulnerability finding records | 866 |
| Unique vulnerability IDs | 548 |
The finding counts by severity are:
| Severity | Finding records |
|---|---|
| CRITICAL | 32 |
| HIGH | 217 |
| MEDIUM | 348 |
| LOW | 238 |
| UNKNOWN | 31 |
The 866 records do not mean there are 866 different CVEs. A CVE affecting multiple packages can produce multiple records. These counts also cover packages throughout the image, not just nginx itself.
These figures summarize the scan taken at the time shown above. Running the same command again does not necessarily produce the same results.
Overall JSON structure
With only the main fields included, the JSON output has this structure:
{
"Trivy": {
"Version": "0.71.2"
},
"ArtifactName": "nginx:1.20",
"ArtifactType": "container_image",
"Metadata": {
"OS": {
"Family": "debian",
"Name": "11.3"
}
},
"Results": [
{
"Target": "nginx:1.20 (debian 11.3)",
"Class": "os-pkgs",
"Type": "debian",
"Packages": [],
"Vulnerabilities": []
}
]
}
This example illustrates the overall structure and omits some fields.
Packages and Vulnerabilities are shown as empty arrays for clarity; the
actual scan results contain package and vulnerability records.
Metadata describes the scan target, while Results is an array of results
for individual targets. The example shows one element in Results. That
element has a Packages inventory and a Vulnerabilities list.
The output can be divided into three main groups:
| Group | Contents |
|---|---|
| Report information | Trivy version, creation time, target name, and identifiers |
Metadata |
OS, image, layers, build history, and startup configuration |
Results |
Detected packages and vulnerabilities |
To examine vulnerabilities, start with Vulnerabilities in Results, then
consult Packages and Metadata as needed.
Main fields in a vulnerability record
Vulnerability records are stored in the Vulnerabilities array of each
Results element (Results[].Vulnerabilities[]). Here are the main fields
from a record whose PkgName is apt:
{
"VulnerabilityID": "CVE-2011-3374",
"PkgName": "apt",
"InstalledVersion": "2.2.4",
"Status": "affected",
"Severity": "LOW",
"SeveritySource": "debian"
}
| Field | How to read it |
|---|---|
VulnerabilityID |
Which vulnerability was detected |
PkgName |
Which package it affects |
InstalledVersion |
The version installed in the image |
FixedVersion |
A version with a fix; omitted when that information is unavailable |
Status |
The remediation status reported by the vulnerability source |
Severity |
The severity selected by Trivy |
SeveritySource |
The source of the selected severity |
This record reports that apt 2.2.4 is affected by CVE-2011-3374 and uses Debian's LOW severity rating. It does not tell you whether a running application calls the vulnerable functionality.
How Status relates to the fixed version
The same scan's Results[].Vulnerabilities[] also contains a record whose
PkgName is bsdutils. Its main fields are:
{
"VulnerabilityID": "CVE-2024-28085",
"PkgName": "bsdutils",
"InstalledVersion": "1:2.36.1-8+deb11u1",
"FixedVersion": "2.36.1-8+deb11u2",
"Status": "fixed"
}
Status: fixed means a fixed version is available, not that the image has
already been fixed. Here, the installed version ends in deb11u1, while
the fixed version is deb11u2.
The statuses and their finding counts in this JSON output are:
| Status | Meaning | Finding records |
|---|---|---|
fixed |
A fixed version is available | 437 |
affected |
The package is listed as affected | 305 |
fix_deferred |
The fix has been deferred | 90 |
will_not_fix |
There are no plans to fix it | 34 |
An absent FixedVersion does not mean the package is safe or unaffected.
A fix may not be available, or the information may not have been
recorded.6
Severity selection and CVSS
Severity is a rating that Trivy selects from external vulnerability
information. It is not a CVSS score calculated independently by Trivy.
Trivy selects external assessments and, when necessary, maps them to a severity level. By default, it prefers the relevant vendor's severity. If that is unavailable, it derives a severity from the supplied CVSS score. If that information is also unavailable, it consults sources such as NVD.
When NVD and Debian rate the same CVE differently, Trivy's Severity may
therefore differ from what you see in NVD. Vendors can account for
distribution details such as build options and default settings.7
The earlier apt record contains these assessment fields:
{
"Severity": "LOW",
"SeveritySource": "debian",
"VendorSeverity": {
"debian": 1,
"nvd": 1
},
"CVSS": {
"nvd": {
"V2Score": 4.3,
"V3Score": 3.7
}
}
}
This excerpt includes NVD scores in CVSS, but its SeveritySource is
debian. The presence of CVSS.nvd does not mean the displayed severity
was determined solely from NVD's scores.
VendorSeverity uses enumeration values: 0 for UNKNOWN, 1 for LOW, 2 for
MEDIUM, 3 for HIGH, and 4 for CRITICAL. These are not CVSS scores.
CVSS can also contain assessments from different CVSS versions for each
source. A V3Vector beginning with CVSS:3.1 represents a v3.1 assessment.
Not every CVE has a v4.0 score.
Combining results with KEV and EPSS
This scan's JSON includes CVSS assessments, but no dedicated fields for KEV membership or EPSS scores.
| Information | What it tells you | How to obtain it for these results |
|---|---|---|
| CVSS | Technical severity | Read CVSS in the JSON output |
| KEV | Whether CISA has confirmed exploitation and included the CVE in its catalog | Match CVE IDs against the KEV Catalog |
| EPSS | The estimated probability of exploitation in the wild within the next 30 days | Retrieve scores using CVE IDs |
CISA publishes KEV data as JSON and CSV. Absence from the catalog does not prove that a vulnerability has not been exploited.8
FIRST provides EPSS through an API and CSV files, among other formats. The API is useful for looking up a small number of CVEs, while daily CSV files are useful for bulk retrieval. EPSS is not the probability that your particular server will be compromised.910
To enrich Trivy results with this information, use VulnerabilityID as the
common key.
Considerations when using scan results
No reported vulnerabilities does not necessarily mean safe
This scan confirmed that nginx was present in the image, but did not report any vulnerabilities for nginx.
Completing an image scan does not mean every package in the image was checked for vulnerabilities. If nginx was excluded from vulnerability scanning, its vulnerabilities would not be detected.
For example, Trivy uses Debian's vulnerability information when checking Debian packages. That information covers packages distributed by Debian. Packages installed from another source, such as the nginx developers, may be excluded from the scan.11
The nginx package in this example was also recorded as coming from a source other than Debian. These results alone do not establish whether it was checked, so the absence of reported vulnerabilities cannot establish that it is safe.
Check OS end-of-support information
This scan recorded the following values in Metadata.OS:
This records Trivy's assessment that the OS had reached the end of support at the time of the scan. It does not necessarily account for current support contracts or every extended support program. Consult the OS provider's information when making operational decisions.
Results can change for the same image
Even if an image is unchanged, newly published vulnerabilities and corrections to existing information can change the findings. This is why rescanning an image later is useful, even if it was scanned when built.
To investigate differences, record the image digest, Trivy version, scan time, options, and information about the vulnerability database used.
Filtered vulnerabilities still exist
For example, --ignore-unfixed excludes findings such as vulnerabilities
without an available fix. This can help focus on actionable fixes, but it
does not provide a complete picture.
Severity filters and exclusion settings have the same limitation. Before comparing finding counts, check that the scan conditions match.6
JSON field reference
This section lists fields in this scan's JSON output, including fields not covered earlier. It is not a complete schema shared by every Trivy scan target.
The structure below shows where the fields belong. Metadata and Results
are both top-level properties. Packages and Vulnerabilities are
properties of each element in the Results array.
This JSONC example includes explanatory comments. Some fields are omitted,
and hash values are replaced with "...". Trivy's actual JSON output does
not contain comments.
{
"SchemaVersion": 2, // Version of the report's JSON structure
"Trivy": {
"Version": "0.71.2" // Trivy version used for the scan
},
"ArtifactName": "nginx:1.20", // Name of the scan target
"Metadata": { // Information about the target image
"OS": {
"Family": "debian", // OS distribution in the image
"Name": "11.3" // OS version
},
"Layers": [ // Image layers
{
"Digest": "..." // Hash of this layer
}
],
"ImageConfig": {
"architecture": "amd64" // CPU architecture of the image
}
},
"Results": [ // Results for individual targets
{
"Class": "os-pkgs", // This element contains OS package scan results
"Packages": [ // Packages found in the image
{
"Name": "apt", // Package name
"Version": "2.2.4" // Package version
}
],
"Vulnerabilities": [ // Detected vulnerabilities
{
"VulnerabilityID": "CVE-2011-3374", // Vulnerability ID
"PkgName": "apt", // Package affected by this vulnerability
"InstalledVersion": "2.2.4" // Version of that package
}
]
}
]
}
Each section below identifies where its fields belong. A dot (.)
separates levels in the property hierarchy, and [] represents each array
element.
Report information (top level of the JSON)
These are top-level properties, except for Trivy.Version, which is the
Version property of the top-level Trivy object.
| Field | Meaning |
|---|---|
SchemaVersion |
JSON structure version; 2 in this example |
Trivy.Version |
Trivy version used for the scan |
ReportID |
Report identifier |
CreatedAt |
Report creation time |
ArtifactID |
Identifier Trivy uses for the scan target |
ArtifactName |
Target name |
ArtifactType |
Target type; container_image in this example |
Metadata (target image information)
These fields belong to the top-level Metadata object.
Field in Metadata |
Meaning |
|---|---|
Size |
Total image layer size in bytes |
OS.Family |
OS distribution family |
OS.Name |
Detected OS version |
OS.EOSL |
Trivy's end-of-support assessment |
ImageID |
Image identifier |
Reference |
Target image reference string |
RepoTags |
List of tags |
RepoDigests |
References combining repository names and digests |
DiffIDs |
Hashes of uncompressed layers |
Layers |
Information about individual layers |
Layers[].Size |
Size of each layer in bytes |
Layers[].Digest |
Hash of the distributed layer data |
Layers[].DiffID |
Hash of the uncompressed layer data |
ImageConfig |
Image configuration; its fields are described in the next table |
Identifiers and hashes serve different purposes. Similar names do not make them interchangeable.1213
ImageConfig (configuration in Metadata)
These fields belong to Metadata.ImageConfig. They describe configuration
recorded in the image.
Field in Metadata.ImageConfig |
Meaning |
|---|---|
architecture |
CPU architecture; amd64 in this example |
os |
OS type; linux in this example |
created |
Image creation time |
history |
Build history |
history[].created |
Creation time of each build step |
history[].created_by |
Command or other information describing how the step was generated |
history[].empty_layer |
true if the step does not add a filesystem layer |
rootfs.type |
Filesystem structure type; layers in this example |
rootfs.diff_ids |
Uncompressed hashes of the constituent layers |
config.Entrypoint |
Program executed at startup |
config.Cmd |
Default command and arguments |
config.Env |
Environment variables |
config.Labels |
Additional metadata, such as maintainer information |
config.Labels.maintainer |
Label identifying the maintainer |
config.ExposedPorts |
Intended ports; 80/tcp in this example |
config.StopSignal |
Signal used to stop the container; SIGQUIT in this example |
ExposedPorts alone does not publish a port on the host. Environment
variables and startup commands can also be overridden at runtime, so these
fields do not describe the observed state of a running container.14
Results (results for individual targets)
These fields belong to each element of the top-level Results array.
Field in Results[] |
Meaning |
|---|---|
Target |
Target name for this result |
Class |
Result classification; os-pkgs for OS packages in this example |
Type |
Type of target analyzed; debian in this example |
Packages |
Inventory of detected packages |
Vulnerabilities |
List of vulnerability finding records |
Packages (package inventory in Results)
These fields belong to each element of Results[].Packages[].
Field in Results[].Packages[] |
Meaning |
|---|---|
ID |
Package ID, such as adduser@3.118 |
Name |
Package name |
Identifier.PURL |
Standard Package URL identifying the package type, name, version, and other attributes |
Identifier.UID |
Identifier used to distinguish packages |
Version |
Package version |
Release |
Distribution package revision |
Epoch |
Numeric value used to adjust version comparison order |
Arch |
Supported architecture; all means architecture-independent |
SrcName |
Name of the source package |
SrcVersion / SrcRelease / SrcEpoch |
Source package version information |
Licenses |
List of licenses |
Maintainer |
Package maintainer |
Repository.Class |
Repository classification: official for the OS provider's repository, or third-party for another provider |
DependsOn |
IDs of packages this package depends on |
Layer.Digest / Layer.DiffID |
Layer hashes associated with the package |
InstalledFiles |
Paths of installed files belonging to the package |
AnalyzedBy |
Analyzer used; dpkg in this example |
The presence of license information or file lists does not itself indicate that a problem was detected.15
Vulnerabilities (vulnerability list in Results)
These fields belong to each element of Results[].Vulnerabilities[].
Field in Results[].Vulnerabilities[] |
Meaning |
|---|---|
VulnerabilityID |
Vulnerability identifier, such as a CVE ID |
PkgID / PkgName |
ID and name of the affected package |
PkgIdentifier.PURL / PkgIdentifier.UID |
Identifiers for the affected package |
InstalledVersion |
Installed version |
FixedVersion |
Version with a fix |
Status |
Remediation status reported by the information source |
Layer.Digest / Layer.DiffID |
Layer information for the affected package |
Severity |
Selected severity |
SeveritySource |
Source of the selected severity |
VendorSeverity |
Enumerated severity values by source |
CVSS |
CVSS assessments by source |
CVSS.*.V2Score |
CVSS v2 score; * represents a source name such as nvd |
CVSS.*.V3Score |
CVSS v3 score |
CVSS.*.V40Score |
CVSS v4.0 score |
CVSS.*.V2Vector |
Vector string describing the CVSS v2 assessment |
CVSS.*.V3Vector |
Vector string describing the CVSS v3 assessment |
CVSS.*.V40Vector |
Vector string describing the CVSS v4.0 assessment |
CweIDs |
CWE IDs classifying the type of weakness |
Title / Description |
Title and detailed description |
PrimaryURL |
Main page with further details |
References |
List of related resource URLs |
DataSource.ID / DataSource.Name / DataSource.URL |
ID, name, and URL of the advisory source used for detection |
VendorIDs |
Vendor advisory IDs and similar identifiers |
Fingerprint |
Hash identifying a combination of target, package, vulnerability, and related attributes |
PublishedDate |
Publication time of the vulnerability information |
LastModifiedDate |
Last modification time of the vulnerability information |
PublishedDate and LastModifiedDate do not indicate when the vulnerability
was first detected in this image. DataSource and SeveritySource also
serve different purposes: the source used for detection and the source of
the selected severity, respectively.16
Summary
Trivy is a security scanner that detects known vulnerabilities and configuration issues in targets such as container images, local files, and Git repositories.
- Scan coverage depends on the target and options.
- JSON output includes package inventories, vulnerability records, and image configuration.
- The number of finding records differs from the number of unique vulnerability IDs.
Status: fixedindicates that a fix is available, not that the target image has been fixed.- Read
Severitytogether withSeveritySourceandCVSSto understand the assessment. - Detecting a package does not necessarily mean it was checked against vulnerability information.
- Matching CVE IDs against KEV and EPSS adds information for prioritizing remediation.
When reading results, distinguish between which packages are present, what was detected by matching vulnerability information, and what you should prioritize in your environment.
Finding counts and severity alone do not determine impact or remediation priority. Check the scope of the scan and the basis of the assessments, then consider fix availability, observed exploitation, and how the packages are used.
References
Document reviewed: September 10, 2026. The counts and JSON excerpts in this article are based on a scan performed with Trivy 0.71.2 on September 9, 2026.
KestreLynx is open-source software that regularly scans images used by running Docker and Kubernetes containers with Trivy and sends changes since the last scan and priorities based on severity, CISA KEV, and EPSS to Slack or a webhook. For Docker and Compose, remediation plans and pull requests (experimental) support remediation from comparing update candidates to creating GitHub pull requests, with both features disabled by default. Users handle merging, rebuilding, and deployment.