Summary:
Syft does not detect certain components (nghttp2, brotli, and sqlite) in a container image created with an Ubuntu base. The components are expected to appear in the SBOM but are missing.
Steps to Reproduce:
Create a container image using the following setup:
Can you share a Dockerfile/Containerfile as part of your steps to reproduce? “Custom application libraries” doesn’t tell me about what exactly was installed or how. Did you use apt? snap? curl?
It will be much easier for us to investigate if you could share a specific Dockerfile.
Yes please find the contents of the Dockerfile and all the application related libraries(like libsqlite3.so.0, libsqlite3.so.0.8.6, libnghttp2.so.14, libbrotlicommon.so.1, libbrotlidec.so.1, libbrotlienc.so.1) are present locally which are later copied through the Dockerfile.
From ubuntu:18.04
RUN apt-get update
RUN mkdir newtest
COPY . ./newtest
Copying binaries directly into the image means that no package manager has knowledge of those binaries. For example, if you did an apt install libsqlite or whatever the package is called, then apt would have an entry in its state that was evidence of that installation, and Syft would find that.
For binaries that are just copied into the file system and not managed by any package manager, Syft has two strategies for categorizing them: binary classifiers and ELF metadata.
Binary classifier cataloger
The binary classifier cataloger attempts to identify binary files by inspecting their contents (sort of a slightly-more-sophisticated strings my-binary | grep approach). For many common binaries, Syft has regular expressions designed to match these binaries and their versions:
Each of those objects is essentially a file glob and a regex that attempts to identify files matching that glob as particular versions of a particular binary.
ELF metadata cataloger
This cataloger, defined at syft/syft/pkg/cataloger/binary/elf_package_cataloger.go at main · anchore/syft · GitHub, asks Syft for all files with certain mime types, (including application/x-sharedlib, which is how an ELF .so file should be classified), and uses a process analogous to readelf to get the notes section out of the ELF, to see whether someone has added notes identifying the ELF file.
Why your packages aren’t detected
If Syft has an ELF file that has no notes identifying it and doesn’t regex match to some well-known binary, and it wasn’t installed by any package manager, then Syft isn’t able to make a package, because it doesn’t have a way to determine the version, and the minimal information we report in a package is name and version.
What Syft still finds
Although Syft isn’t able to find a package version in this setup, it is able to find a file. If you invoke syft like this: SYFT_FILE_METADATA_SELECTION=all syft -o json my-image, then Syft will put a files section in the SBOM with information like mode, digest, and mimetype for every file in the image. Then you could independently note the digests of the .so files you’re mounting into the image and keep track that way. (Note that this can also take a while and make a really large SBOM.)
Options
These are some things you could do to make it so Syft finds your .so files:
Get the .so files by installing it in your Dockerfile, e.g. RUN apt-get install -y libsqlite3-0
If you are building these shared libraries, consider adding notes to the ELF metadata that identify the packages
If these packages are from well-known, official distributions (e.g. you’re downloading libsqlite from an official release page or something) consider adding a binary classifier to Syft that will match these.
Use the files section of the SBOM instead of the artifacts section for these packages, as described above.
I hope this has answered your question. Let me know if you’d like more information about one of these options.