While working with a client a few years ago, I was introduced to the concept of a Software Bill of Materials, colloquially known as an SBOM. It didn’t take long before I recognized its immense value and importance in improving security and integrity in software development. Hopefully, over the next few minutes as you read this blog, you’ll start to see that as well.
The topic of SBOMs has become more and more popular over the past several years and is increasingly critical in this technology-driven world. We’ve all heard of numerous enterprise-level data attacks, exposures, and leaks in recent years, and almost all are caused by some sort of security vulnerability. Many of these incidents could have been realized and possibly even mitigated before disaster struck if an SBOM had been in play.
What is a Software Bill of Materials?
So, what is this magical concept? I’m glad you asked. In its simplest conceptual form, an SBOM is like a very detailed recipe for a homemade, one-of-a-kind cake. On the recipe card, you would, of course, list out the ingredients that were used. But then, you would go further by detailing even the specific brand of each ingredient. And then, you would go even further by specifying whether the ingredients were composed of other items and continuing to break the list down to its smallest forms, quantities, expiration dates, and more. Ultimately, the recipe becomes an extremely detailed list of every ingredient and process that goes into making the cake.
In the manufacturing world, a bill of materials is a complete structured record of what is used to manufacture a product: the parts and components, assemblies, instructions, etc. An SBOM includes similar information about what was used to make a piece of software. The Software Bill of Materials records information like the third-party dependencies and libraries utilized, the relationship between the dependencies, all the versions, any licenses that apply to components, any suppliers, the author(s), and more.
Why is an SOBM Important?
Why do we need to know all of this information? Well, let’s think about it in terms of our cake example. What if you found out that one of the ingredients you used to make your cake had some sort of problem – maybe it was expired, perhaps contaminated, or otherwise compromised? Imagine if one of the ingredients you used could cause an allergic reaction or a health issue.
You would want to know about it even if it was just for your own personal consumption! And what if you used the comprised ingredient to make more than one cake along with some brownies or cookies? What if you had given some away to neighbors or sold a few pans to customers? In all of those cases, you would want to be transparent and let anyone who sampled your baked goods aware as soon as possible.
By that way of thinking, the more information you record and know about the processes and ingredients used, the better off you are. The more you know, the more equipped you are to swiftly handle a crisis if it arises. Software development is no different. Recording information about the “ingredients” and processes used is vital to improving safety and security because it facilitates traceability.
If you develop software, creating an SBOM should be part of your development process, ideally as a step within your continuous delivery, so it’s updated with each build. It is essential for quality and integrity to be proactive in creating and maintaining a Software Bill of Materials. You need to know and record not only the primary direct dependencies but also the transitive dependencies. You should be monitoring and auditing this information constantly for vulnerabilities and addressing them quickly.
Generating a Software Bill of Materials
So, now that you know what an SBOM is, let’s talk about how to generate one. There are several open-source, free tools available (likely even more to come in the future). Most are very simple, straightforward CLI-style tools, geared toward specific languages or tech stacks like Maven or npm. For brevity, I’ll demonstrate the use of CycloneDX-node-npm to generate an SBOM for the Keyhole project, KHS-next-example, so we can review the output.
To use CycloneDX-node-npm, you can install it globally with an npm command, or you can skip installing and use it with npx directly as a part of the CycloneDX-npm command. For CycloneDX to be able to generate the SBOM, it needs the package-lock.json file and node_modules folder of the project you’re generating it for – since it needs to be able to traverse the list of dependencies and gather all of its data. So to generate the SBOM, the command is as simple as executing the following in a terminal window:
cyclonedx-npm --output-file=SBOM.json
There are a handful of parameters available, but let’s keep it simple by only specifying the output file name instead of having it output to standard out. Many of the default value options are good to leave as are and don’t need modification for most use cases.
Almost instantly, we’re given the SBOM.json file filled with over 22k lines. That’s it! It’s even easier and faster than using an instant cake mix. Here’s a collapsed view of the result.
Looking through the file, you’ll see there are 3 primary sections (Metadata, Components, and Dependencies) and then numerous subgroups.
Just by the line count, you can tell that the Components Section (seen below) takes up most of the file. This makes sense since it lists every individual library incorporated in the application and details on each, including licenses and URLs.
The Dependencies Section (shown below) shows the relationship and interdependency of all of the libraries listed in components. For each dependency, the SBOM provides a list of what it "dependsOn"
. So, you end up with a list down to the lowest level artifact in the hierarchy – those items are indicated as lone refs without any further dependencies.
For example, in the following screenshot, nextjs-template
has a dependency of @types/nodes
which has a dependency of undici-types
. And undici-types
doesn’t have any further dependencies of its own, so it’s shown by itself as a ref with no "dependsOn”
section.
On the surface, this just seems like a bunch of semi-useful information with no apparent value. However, as with most collected data, the value comes from putting it to use. Generating the Software Bill of Material is just one of the first steps in our proverbial recipe process; we need to actually do something with these SBOMs. We need to process and monitor them, watching for vulnerabilities within our applications.
Processing and Monitoring the SBOM
There are several tools available to process and monitor SBOMs, both open-source and commercially licensed, paid-for options. One of my personal favorites is Dependency Track, made by the OWASP Foundation. It has many great features and integrations and is open-sourced.
Dependency Track can easily be deployed as a Docker Container. Their quick start guide covers all the necessary requirements and options available. For this example, I’ve used their Docker compose option, which downloads a docker-compose.yml file and starts up the API server on localhost:8081 and the front-end on localhost:8080. On the front-end, we get the initial login page and, after logging in, the dashboard appears.
Now we need to get our SBOMs into Dependency Track. There are a few ways to achieve this goal. The UI allows for both manual creation of projects and uploads of SBOMs, which work fine for small and occasional usage. However, for the best option and the goal of continuous integration, using a Jenkins plugin, GitHub action, or curl commands is highly recommended. More details about usage, along with examples, are documented on their Usage: CI/CD page.
As they do in all of the cooking shows on TV, I’m not going to show you the baking process. (or in this case, the uploading of the SBOMs). Instead, let’s jump ahead to the results. Ta-da! We now have a colorful dashboard filled with interesting information to digest. It now shows the portfolio of projects highlighting vulnerabilities and risks in graph and numeric form.
I won’t go through every tab and view on Dependency Track for the sake of time, but I do want to highlight a few specific views that I find valuable. As you click through the individual project tabs, you’ll see that each gives more information at a deeper level.
Here’s where we can really start to see the SBOM data being used to highlight sources of vulnerability. As you can see, this simple project clearly has a handful of issues that need to be addressed with a few vulnerabilities ranging from medium to critical.
The Components tab displays all the libraries included in the project, similar to the long list we saw in the SBOM JSON file earlier.
The Audit Vulnerabilities tab, on the other hand, is solely focused on highlighting all vulnerable libraries contained within this singular project.
Let’s think back to our baking example; what if we wanted to identify all baked goods that had a bad ingredient? We have that ability with Dependency Track!
We can search for dependencies across all projects via the Components view under Portfolio. Below, I’ve searched for the library “tough-cookie” (a coincidental but ideal library name), which has a critical vulnerability with its version 2.5.0 (as we saw in the screenshot above). We can see that the library is being used in two of the projects.
In my opinion, this is one of the best features. It’s extremely helpful to be able to instantly find which projects are impacted by a vulnerability with very little effort.
We can also get another broader look at this from the Vulnerability Audit view and see all vulnerabilities across the portfolio.
We’ve only scratched the surface on Dependency Track and its features. For more information on Dependency Track and its numerous capabilities, I highly recommend checking out their documentation. It’s thorough and provides great insight into the tool.
Hopefully, with even just these simple examples, you’ve started to see the value in having a Software Bill of Materials – it gives visibility into vulnerabilities across your portfolio. Adding these steps into your CI/CD processes takes very little effort and, in most cases, little to no additional cost. The benefits are immensely worth it.
You can have your cake and eat it too!
Final Thoughts
As with most everything in the software world, the SBOM space is an ever-evolving and expanding landscape. The formats and tools may come and go, but the concepts will still apply and be relevant. Software security and integrity should always be at the forefront of every development effort. The sooner you start implementing these elements into your processes, the better and safer your software will be, and the sooner you can respond to incidents.
Instituting a Software Bill of Materials procedure as a part of your continuous delivery process is clearly a recipe for success!
Looking to stay ahead in the ever-evolving world of software development? Check out more insights, tips, and best practices on the Keyhole Dev Blog. Explore a wealth of articles designed to help you build better, more secure software!
Additional Resources:
- Software Bill of Materials (SBOM) – Cybersecurity and Infrastructure Security Agency
- SOFTWARE BILL OF MATERIALS – National Telecommunications and Information Administration
- CycloneDX – OWASP Foundation
- Dependency-Track – OWASP Dependency Track