Description
Currently, when Trivy scans locally built Docker images that don't have RepoDigests (i.e., images that haven't been pushed to a registry), it doesn't generate an OCI PURL in the output. This causes the purl field to be null, which makes it difficult to apply vulnerability suppressions, like VEX, consistently.
Problem
When scanning local images without RepoDigests, Trivy's CycloneDX output shows:
{
"metadata": {
"component": {
"type": "container",
"name": "test:latest",
"bom-ref": "3ff14136-e09f-4df9-80ea-000000000002",
"purl": null
}
}
}
The missing PURL prevents:
- Consistent VEX matching across different scanning contexts
- Reliable vulnerability suppression for local development workflows
- Proper SBOM identification when images are scanned before being pushed to registries
Current Design Rationale
The current behavior of not generating PURLs for local container images was intentional. Since PURLs are defined to "identify and locate" software packages, generating PURLs for local container images seemed incorrect because:
- Local images cannot be located from outside the host machine
- We cannot obtain the repository digest that would serve as the version component in the PURL
- The absence of
RepoDigests indicates the image hasn't been distributed
This was considered the correct behavior according to the original interpretation of the PURL specification.
Proposed Solution
After reviewing the PURL specification discussions, we've concluded that using OCI PURLs primarily for identity (rather than location) doesn't violate the specification. Therefore, we can always generate OCI PURLs for container images, even when they lack RepoDigests.
For local images, use the image name from RepoTags to construct a valid PURL with repository_url as an optional hint qualifier.
Expected Behavior
After the fix, local images should generate proper PURLs:
Local image with latest tag:
{
"metadata": {
"component": {
"type": "container",
"name": "test:latest",
"bom-ref": "pkg:oci/test?repository_url=index.docker.io%2Flibrary%2Ftest&arch=amd64",
"purl": "pkg:oci/test?repository_url=index.docker.io%2Flibrary%2Ftest&arch=amd64"
}
}
}
Local image with specific tag:
{
"metadata": {
"component": {
"type": "container",
"name": "test:v1.0",
"bom-ref": "pkg:oci/test?repository_url=index.docker.io%2Flibrary%2Ftest&tag=v1.0&arch=amd64",
"purl": "pkg:oci/test?repository_url=index.docker.io%2Flibrary%2Ftest&tag=v1.0&arch=amd64"
}
}
}
Discussed in #9381
Description
Currently, when Trivy scans locally built Docker images that don't have
RepoDigests(i.e., images that haven't been pushed to a registry), it doesn't generate an OCI PURL in the output. This causes thepurlfield to benull, which makes it difficult to apply vulnerability suppressions, like VEX, consistently.Problem
When scanning local images without
RepoDigests, Trivy's CycloneDX output shows:{ "metadata": { "component": { "type": "container", "name": "test:latest", "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", "purl": null } } }The missing PURL prevents:
Current Design Rationale
The current behavior of not generating PURLs for local container images was intentional. Since PURLs are defined to "identify and locate" software packages, generating PURLs for local container images seemed incorrect because:
RepoDigestsindicates the image hasn't been distributedThis was considered the correct behavior according to the original interpretation of the PURL specification.
Proposed Solution
After reviewing the PURL specification discussions, we've concluded that using OCI PURLs primarily for identity (rather than location) doesn't violate the specification. Therefore, we can always generate OCI PURLs for container images, even when they lack
RepoDigests.For local images, use the image name from
RepoTagsto construct a valid PURL withrepository_urlas an optional hint qualifier.Expected Behavior
After the fix, local images should generate proper PURLs:
Local image with latest tag:
{ "metadata": { "component": { "type": "container", "name": "test:latest", "bom-ref": "pkg:oci/test?repository_url=index.docker.io%2Flibrary%2Ftest&arch=amd64", "purl": "pkg:oci/test?repository_url=index.docker.io%2Flibrary%2Ftest&arch=amd64" } } }Local image with specific tag:
{ "metadata": { "component": { "type": "container", "name": "test:v1.0", "bom-ref": "pkg:oci/test?repository_url=index.docker.io%2Flibrary%2Ftest&tag=v1.0&arch=amd64", "purl": "pkg:oci/test?repository_url=index.docker.io%2Flibrary%2Ftest&tag=v1.0&arch=amd64" } } }Discussed in #9381