grype: grype cannot scan a local image that was not archived by tar or pushed to a registry
I have the following pipeline in Tekton:
params:
- name: IMAGE
- name: BASE_IMAGE_TRIVY
type: string
default: "aquasec/trivy:0.41.0"
- name: BASE_IMAGE_GRYPE
type: string
default: "anchore/grype:v0.62.1-debug"
- name: PATH_CONTEXT
description: The build context.
default: "."
steps:
- name: trivy
image: $(params.BASE_IMAGE_TRIVY)
workingDir: $(workspaces.source.path)/$(params.PATH_CONTEXT)
script: |
#!/usr/bin/env sh
set -ex
trivy image $(params.IMAGE)
- name: grype
image: $(params.BASE_IMAGE_GRYPE)
workingDir: $(workspaces.source.path)/$(params.PATH_CONTEXT)
script: |
#!/busybox/sh
set -ex
/grype $(params.IMAGE)
Trivy manages to scan the image built with Kaniko, while grype
causes an error (it does not find this image locally and tries to pull it from remote):
+ /grype some_aws_image:latest
1 error occurred:
* failed to catalog: could not fetch image "some_aws_image:latest": unable to use OciRegistry source: failed to get image descriptor from registry: GET https://some_aws_image_link: unexpected status code 401 Unauthorized: Not Authorized
I also tried grype
locally. Although, when I install this until via brew, it works alright and can scan images present on the machine. But I cannot scan local images with the grype
docker container. The option --volume /var/run/docker.sock:/var/run/docker.sock
does not help.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 22 (9 by maintainers)
@mirekphd thanks for the additional info, unfortunately I still have not been able to reproduce:
If I run with verbose logging (
-vvv
) I see:Which shows that the underlying lib is selecting the
DockerDaemon
as expected.I can use the
registry
scheme in the command to force getting the same behavior you’re seeing:… however, that’s because this scheme forces grype down this path, but the example before this shows the correct default behavior (it reaches out to the local docker daemon).
At a surface level this looks closer to what @tgerla mentioned earlier, where the docker socket might be inaccessible.
If I try again but use a different socket path, I can also get the same (bad) behavior:
… which is expected since the docker socket simply isn’t accessible.
When the docker socket can’t be found it searches for a podman socket, then containerd socket, then finally attempts to reach out to the registry.
@mirekphd can you post the results of your failed run with verbose logging?
I think you will see similar output as above, showing that it’s attempting these local options before getting to OCI. Since docker is the first default it doesn’t show “trying docker socket” in the log (we should add that to make it a little more clear though).
They work fine, but are not sufficient. What differs in real-life settings when the error is raised:
mirekphd
in the Docker Hub)So starting from the above example let’s trigger the issue. I’ve built an and pushed as
mirekphd/test-image:20231005
a test image based onalpine:latest
as above. As expected from pushed images no amount of tagging could then stop Grype scans from working (even those including full remote repo name):SUCCESS:
docker.io
tags):However, when I changed the base image to include a never-before pushed (to my namespace) base image with
ubuntu:latest
(I have pushed onlyubuntu:22.04
), so that the image ID changed to a never-pushed96aa83446e66
, then the Grype scan revealed that it needs after all to pull the image from the remote repo before the scan…More info in the log below:
Note I use a dockerized grype. So the contents of the used scanning script are:
@YevheniiPokhvalii it’s not restricted to Kanico, you can update the issue title, as the classic
docker build
is sufficient to reproduce the issue (see scenarios below). Looks likegrype
pulls manifest data (or even entire images) from remote registry, and hence it scan only remote images, i.e. ones that have been already pushed to a registry.If
grype
OSS version had a--container_type
(or--container-type
) flag like thegrype
fork made by Harness apparently does, it would be permanently set to:--container_type="docker_v2"
rather than the setting needed for scanning locally build, unpushed images, which was long possible under Clair (and e.g.clair-scanner
) and is now also possible with Trivy (as per OP report):--container_type="local"
One consequence is that
grype
scans won’t work on air-gapped servers that have no access to any registry, which is different from how Clair and its clients work - they let you scan local images without pushing them first to a registry. But as a redeeming feature (a side note here, but something that needed to be excluded first), it does not have a root requirement (all of the tests below were executed using the officialanchore/grype:latest
container run with docker under a non-root user belonging to thedocker
group).@wagoodman to reproduce the issue:
I. FAIL scenario
docker build
an image; do not push it; In my case I can usemirekphd/ml-cache:20230726
as an example of an image available locally (e.g. fordocker run
) but never pushed to the Docker Hub.grype
and you will get something like this:vs.:
II. SUCCESS scenario
docker build
an image;mirekphd/ml-cache:20230727
as an example of an image already pushed to the Docker Hub (to a public repo)grype
and you will likely succeed, like this: