Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fails to discern locally-built apk packages from distro-provided ones #827

Open
kaniini opened this issue Jul 13, 2022 · 6 comments
Open
Labels
bug Something isn't working needs-investigation

Comments

@kaniini
Copy link

kaniini commented Jul 13, 2022

What happened:

We built a test image with a locally built nginx package: distroless.dev/nginx:latest

The locally built nginx package is matched against Alpine vulnerability data, despite not being from the Alpine ecosystem. The package is pinned to a third-party repository per /etc/apk/world:

pestilence:~$ docker run --entrypoint /bin/sh -it distroless.dev/nginx:latest -c "cat /etc/apk/world"
alpine-baselayout-data
nginx@local
s6

What you expected to happen:

Locally built packages should not match against security data provided by a vendor. This should be detected by matching whether the package UUID (APKINDEX C: field) matches any UUIDs in the vendor indices. Or at the very least check if the package is pinned.

How to reproduce it (as minimally and precisely as possible):

grype distroless.dev/nginx:latest

Anything else we need to know?:

Environment:

  • Output of grype version:
pestilence:~$ grype version
Application:          grype
Version:              0.40.1
Syft Version:         [not provided]
BuildDate:            [not provided]
GitCommit:            [not provided]
GitDescription:       [not provided]
Platform:             linux/amd64
GoVersion:            go1.18.3
Compiler:             gc
Supported DB Schema:  3
  • OS (e.g: cat /etc/os-release or similar):
pestilence:~$ cat /etc/alpine-release 
3.16.0
@kaniini kaniini added the bug Something isn't working label Jul 13, 2022
@spiffcs
Copy link
Contributor

spiffcs commented Jul 13, 2022

Thanks @kaniini! We'll take a look here and see if we can add a bit more nuance to the APK cataloger and matcher.

@kaniini
Copy link
Author

kaniini commented Jul 13, 2022

Thanks! There is also /etc/secfixes.d which is an /etc/apk/repositories.d type directory which contains files listing what security feeds are relevant to which pinned repositories. I'm still working on a spec for this though.

@kaniini
Copy link
Author

kaniini commented Jul 13, 2022

Syft is also affected for the same reason.

pestilence:~$ syft packages docker:distroless.dev/nginx:latest -o cyclonedx-json 2>/dev/null | jq .components[35].purl
"pkg:alpine/nginx@1.20.2-r0?arch=x86_64&distro=alpine-3.16"

@joshbressers
Copy link
Contributor

I will try to summarize what I understand below, please correct anything I'm mistaken about, I'm not an Alpine expert.

The package UUIDs aren't easily available, so trying to match against those doesn't seem like an option.

Packages installed from other repositories carry a repository tag. We could try to filter those to match against generic security data rather than the alpine data.

I am unsure how we should construct the PURL for packages such as these (if someone else has an answer please speak up)

@willmurphyscode
Copy link
Contributor

@kaniini I'm interested in picking up this work, but I'm not sure I have enough context to start implementing right away. Could you or @joshbressers help me understand:

Packages installed from other repositories carry a repository tag. We could try to filter those to match against generic security data rather than the alpine data.

Is this tag detectable in the built image? Is it specified somewhere I can go read about?

@willmurphyscode
Copy link
Contributor

Reading through https://wiki.alpinelinux.org/wiki/Apk_spec#Installed_Database_V2, it looks like we can check for lines that start with s::

s: - repository tag, optional, this will be set if the package is tagged to a repository in the world file (ex: linux@testing)

I read that to mean that, when a package is installed from a particular repository listed in /etc/apk/world, the s: tag can set set on its install entry to indicate which one. That seems to be the situation described in the original request, where nginx@local in /etc/apk/world is a different repository than provided by the distro, and so put it in an s: line in a package would be a signal to grype that this package might not be able to be matched against the namespace corresponding to the distro.

As far as I can tell, distroless.dev/nginx:latest is no longer built that way - the commands in the original post either fail or have different outputs on my machine.

I'm also pretty confused about the use of C:. It's described as a UUID in the original post, but https://wiki.alpinelinux.org/wiki/Apk_spec#APKINDEX_Format defines it as a checksum, not a UUID, and details how it is computed. It looks like this item is different for every package:

/ # cat /lib/apk/db/installed | grep '^C:' | wc -l
17
/ # cat /lib/apk/db/installed | grep '^C:' | sort | uniq | wc -l
17

so I don't think it will be helpful for learning package origins. But I may have misunderstood something in the original post.

I'll keep investigating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs-investigation
Projects
Status: No status
Development

No branches or pull requests

4 participants