How to Create a Software Bill of Materials
While there may be days when you feel like dropping “SBOMs” left and right, in the realm of tech we’re not talking about another term for a four-letter word that starts with “S.”
SBOM stands for Software Bill of Materials and has become a critical security issue for businesses and developers. Essentially, an SBOM is a nested piece of software inventory that comes together to serve a larger whole. SBOMs have become absolutely necessary to maintain the high security standards needed to run a successful business – especially when it comes to supply chain risk management.
You see, all software ever created may or may not contain vulnerabilities. That’s just part of dealing with technology. This is becoming increasingly difficult as software requires more and more dependencies.
let me explain.
Suppose you need to install software X to provide a specific function either on your system or in your supply chain. When you install Software X, you may find that it depends on Software 1, Software 2, Software 3, and Software 4. So in order to install software X, you must also install all of these other pieces.
This is always very evident when installing open source software. For example, if you install something like Node.js, you’ll find that it also requires libc-ares2, libjs-highlight.js, libnode72, and nodejs-doc. You didn’t expect that. And while you may have checked the current vulnerabilities in Node.js, you probably didn’t know to check everything else.
This is especially true when handling containers. Why? Because you depend on images that you didn’t create and over which you have no control. How do you know if the latest NGINX image is vulnerability free? And when you’re building full-stack container deployments, you suddenly have to consider multiple images, each of which can contain vulnerabilities.
To do this, you’ll use a tool to create a software bill of materials for each image you use. One such tool is Syft, which allows you to easily create an SBOM for the images you use. But how do you read this information? Assuming you could find a tool like Syft that generates more data than you want to see, what do you think?
Let’s see if we can dig in and get some clarity.
SBOM standards
Fortunately, standards for SBOMs have been established that provide a common format for describing the build of installed software (or container images) that greatly simplifies the consumption of the reported data.
There are two commonly used standards for SBOMs:
- Software Product Data Exchange (SPDX) – is an international open standard for listing components, licenses and copyrights associated with software. Formats used are RDF, XLS, SPDX, YAML and JSON.
- CycloneDX – Used for use in application security contexts as well as analysis of supply chain components. The formats used are XML and JSON.
SBOMs are used by both security and development teams, so the fact that they adhere to standards makes them much easier to use in general.
What is included in SBOMs?
SBOMs show a complete inventory of the application in question, including all open-source components, licenses, version information, and vulnerabilities. The only limitation is that tools like syft only generate the SBOM, which does not contain any vulnerabilities. To add vulnerabilities to the mix, you would need to add a tool like Grype.
With that said, let’s create a SBOM with syft and then a vulnerability list with grype and see what there is to see.
Generate an SBOM with syft
To install syft, open a terminal window and enter the following command (with administrator privileges):
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s — -b /usr/local/bin
ruffle –sSfl https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s — -b /usr/local/bin |
Once syft is installed, pull in a container image that you want to scan, say:
Now run the scan with:
Syft loads the image and then, once the scan is complete, outputs everything to the terminal. The information displayed looks something like this:
nginx 1.23.1-1~bullseye deb nginx-module-geoip 1.23.1-1~bullseye deb nginx-module-image-filter 1.23.1-1~bullseye deb nginx-module-njs 1.23.1+0.7.6- 1~bullseye deb nginx-module-xslt 1.23.1-1~bullseye deb openssl 1.1.1n-0+deb11u3 deb passwd 1:4.8.1-1 deb perl-base 5.32.1-4+deb11u2 deb readline-common 8.1 -1 deb
nginx 1.23.1–1~direct hit deb nginx–module–geoip 1.23.1–1~direct hit deb nginx–module–picture–filter 1.23.1–1~direct hit deb nginx–module–njs 1.23.1+0.7.6–1~direct hit deb nginx–module–xslt 1.23.1–1~direct hit deb openssl 1.1.1n–0+deb11u3 deb password 1:4.8.1–1 deb Perl–base 5.32.1–4+deb11u2 deb read line–common 8.1–1 deb |
That’s only a fraction of the output you’ll see, and it should be fairly easy to understand. The left column is the name of the software, the middle column is the version number, and the right column is the package manager used to install the application for the container image.
With this information, you can scan each installed package version for known vulnerabilities. Or you could go the easy route and use Grype from Anchore.
Generate a vulnerability report with grype
The SBOM information gives you a lot of details, but it’s missing a very crucial element – vulnerabilities. To do this, we install grype with the command:
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s — -b /usr/local/bin
ruffle –sSfl https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s — -b /usr/local/bin |
Now let’s run a grype scan on the same container image with:
The output of this command includes details like:
passwd 1:4.8.1-1 deb CVE-2007-5686 negligible passwd 1:4.8.1-1 deb CVE-2013-4235 negligible perl-base 5.32.1-4+deb11u2 (will not be fixed) deb CVE-2020 – 16156 Perl High Base 5.32.1-4+deb11u2 deb CVE-2011-4116 Negligible tar 1.34+dfsg-1 deb CVE-2005-2541 Negligible util-linux 2.36.1-8+deb11u1 deb CVE-2022-0563 Negligible zlib1g 1:1.2.11.dfsg-2+deb11u1 deb CVE-2022-37434 Critical
password 1:4.8.1–1 deb CVE–2007–5686 irrelevant password 1:4.8.1–1 deb CVE–2013–4235 irrelevant Perl–base 5.32.1–4+deb11u2 (won‘t fix) deb CVE–2020–16156 High Perl–base 5.32.1–4+deb11u2 deb CVE–2011–4116 irrelevant tar 1.34+dfsg–1 deb CVE–2005–2541 irrelevant useful–Linux 2.36.1–8th+deb11u1 deb CVE–2022–0563 irrelevant zlib1g 1:1.2.11.dfsg–2+deb11u1 deb CVE–2022–37434 Critical |
Now let’s talk. To read the above output:
- Column 1 (far left) – the name of the installed software package.
- Column 2 – the version number of the installed software package.
- Column 3 – Package manager used to install the software.
- Column 4 – CVE Vulnerability List.
- Column 5 – CVE vulnerability assessment.
At this point, you not only know about any software installed in a container image, you also know if it contains known vulnerabilities. This information is invaluable to both your security and development teams. For example, as you can see above, the included zlib1g package in the NGINX container has a critical vulnerability. With the CVE listing, you can research it to see if it’s something that could impact your business. In this case, your development team could either fix the vulnerability or wait for the official NGINX image to be patched.
Although you might be tempted to overlook syft in favor of grype, both tools have their uses. Whichever tool you use to generate your SBOMs, make sure you understand the output so you can use it more effectively.