portrait

Tiexin Guo

Senior DevOps Consultant, Amazon Web Services
Author | 4th Coffee

1. What is BOM

BOM stands for Bill of Materials, which has been used for quite a long time by the automotive industry as a method for the supply chain management.

You might have heard of the term if you are familiar with the automotive industry. Even if you are not, don't worry.

Imagine that you just bought a new car. Maybe your car is built (to be more precise, assembled) by Toyota, Volkswagen, or whatever brand takes your fancy. But, the reality is, nowadays, the division of labor is so common that no car company alone can build all the components a car needs. Many parts are made by other companies, suppliers, or subcontractors worldwide.

The automotive industry's bill of materials (BOM) tells you where each of those parts came from, detailing every component that makes your car run. Suppose a particular batch of parts, for example, airbags, has been recalled by the company that produced them. In that case, your car's manufacturer can refer to the BOM to know which cars that particular batch of airbags ended up with quickly so that it can take action on those affected vehicles.


2. What is SBOM

SBOM stands for Software Bill of Material, which has emerged as a critical component in the software security and supply chain management world.

Although building software isn't exactly like manufacturing a car, there are resemblances, probably more than you might think.

The SBOM work has advanced since 2018 as a collaborative community effort driven by the National Telecommunications and Information Administration's (NTIA) multistakeholder process. According to NTIA's SBOM FAQ, the official definition of SBOM goes as follows:

A Software Bill of Materials (SBOM) is a complete, formally structured list of components, libraries, and modules that are required to build (i.e., compile and link) a given piece of software and the supply chain relationships between them. These components can be open source or proprietary, free or paid, and widely available or restricted access.


3. Why SBOMs play a critical role in security

As the airbag analogy mentioned at the beginning of this blog, it's easy to see that SBOMs play a critical role in security.

It is much quicker and easier to scan a library of SBOMs than to scan your entire infrastructure from scratch. Tools like trivy already support this. In the event of a zero-day, as we recently saw (and will continue to see) with Log4Shell, every minute counts.

SBOMs can also be leveraged by security teams to prioritize issues for remediation based on their presence and location and to create policies specific to component attributes such as vendor, version, or package type, to name a few.

Development teams can also benefit from using SBOMs to track open-source, commercial, and custom-built software components across the applications. This assists developers in managing dependencies, identifying early remediation security issues, and ensuring that developers are using approved code and sources. When a third-party library has a known common vulnerability, if you have an SBOM, you can figure out quickly if the software is affected or not.

Because of its significant implications, SBOMs that can be shared without friction between teams and companies are a core building block of software management for critical industries and digital infrastructure in the coming decades.


4. SBOM Format Standards

An SBOM is a formal, structured record that not only details the components of a software product but also describes its supply chain relationship. An SBOM outlines both what packages and libraries went into your application and the relationship between those packages and libraries and other upstream projects—particularly important when it comes to reused code and open source.

Since an SBOM contains a lot of information, there must be some standards to exchange information effectively, especially with automation. SBOM formats are for that purpose: they are standards for defining a unified structure for generating SBOMs and sharing them with end users or customers. They describe software composition in a standard format that other tools can understand.

The leading SBOM formats are Software Package Data Exchange (SPDX) and CycloneDX, which are both adopted for security use cases.

4.1 SPDX

SPDX is a Linux Foundation project, and its primary goal is to create a standard data exchange format for software packages related information.

Major corporations such as Intel, Microsoft, Siemens, and Sony participate in the SPDX community.

As of now, the latest SPDX specification is version 2.2.2. Specific fields and sections must be present to be considered a valid SPDX document.

4.2 CycloneDX

CycloneDX is a "lightweight SBOM standard designed for use in application security contexts and supply chain component analysis."

Strategic direction and maintenance of the specification is managed by the CycloneDX Core working group, with origins in the longtime security community leader Open Web Application Security Project (OWASP).

What makes CycloneDX unique is that it was designed to be a BOM format and meet a variety of use cases, including software-as-a-service BOM (SaaSBOM).


5. How to Automate SBOM with CI

Of course, a bunch of tools can be used to generate SBOMs, and they can be integrated with your CI system. In this section, we will use GitHub Actions with Syft to do so.

Syft is a CLI tool and Go library for generating an SBOM from container images and filesystems, and it supports both SPDX and CycloneDX formats.

First, let's create a simple Golang application with a module (so that the generated SBOM won't contain nothing).

You can get the code here or fork it directly.

Let's have a look at this simple piece of code: it's a HelloWorld demo calling another Go module:

package main

import (
  "fmt"
    hello "github.com/ironcore864/go-hello-module"
)

func main() {
  fmt.Println(hello.Hello())
}

Then, let's create a GitHub Actions with the following content:

name: SBOM

on:
  release:
    types: [published]

jobs:
  sbom:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          ref: ${{ github.ref_name }}
      - name: Anchore SBOM Action
        uses: anchore/sbom-action@v0.12.0
        with:
          format: cyclonedx-json

This action:

  • runs only when a release is made
  • checks out the tag
  • runs the anchore/sbom-action, which uses syft to generate a CycloneDX format SBOM as a JSON file
  • uploads the JSON file to the release's artifact

After the GitHub Actions file is ready, trigger the job by creating a release. A successful run of the job would look like the following:

github-actions-job-result

If we go to the releases page of the repo, we can see the artifact is uploaded:

github-release-artifact

Now we can download the SBOM and view the content:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "urn:uuid:a61bf508-f014-4cfb-98e5-5564e3699ec1",
  "version": 1,
  "metadata": {
    "timestamp": "2022-10-10T04:45:04Z",
    "tools": [
      {
        "vendor": "anchore",
        "name": "syft",
        "version": "0.53.4"
      }
    ],
    "component": {
      "bom-ref": "af63bd4c8601b7f1",
      "type": "file",
      "name": "."
    }
  },
  "components": [
    {
      "bom-ref": "pkg:golang/github.com/ironcore864/go-hello-module@v0.1.0?package-id=caa41d3c947da3ea",
      "type": "library",
      "name": "github.com/ironcore864/go-hello-module",
      "version": "v0.1.0",
      "cpe": "cpe:2.3:a:ironcore864:go-hello-module:v0.1.0:*:*:*:*:*:*:*",
      "purl": "pkg:golang/github.com/ironcore864/go-hello-module@v0.1.0",
      "properties": [
        {
          "name": "syft:package:foundBy",
          "value": "go-mod-file-cataloger"
        },
        {
          "name": "syft:package:language",
          "value": "go"
        },
        {
          "name": "syft:package:type",
          "value": "go-module"
        },
        {
          "name": "syft:cpe23",
          "value": "cpe:2.3:a:ironcore864:go_hello_module:v0.1.0:*:*:*:*:*:*:*"
        },
        {
          "name": "syft:location:0:path",
          "value": "go.mod"
        }
      ]
    }
  ]
}

Brief explainer here: as expected, we first see a reference to the BOM format (CycloneDX) and version, followed by a unique serial number that corresponds to this unique BOM. If we regenerate the SBOM without changing the contents, this ID will be different.

Then we have some metadata, and finally a list of components. You can see the fields "cpe" and "purl", these are actually vulnerability specifications: CPE is actually somewhat deprecated, but Package URL (PURL) is another standard to universally identify packages.

It means that regardless of what vendor, project, or ecosystem the package belongs to, a unique ID can be associated with it. And therefore it is possible to compute the associated risk against a vulnerability database.

Of course, there are many other features of syft, and you can specify different SBOM formats and file formats. Read more at their GitHub repo.


Summary

With the increasing use of third-party open-source libraries to build containerized, distributed applications, it's more and more challenging to know exactly what parts are in your software. That's why SBOMs are becoming more and more popular.

In this tutorial, you've learned the what, why, and how to use SBOM. If you like this article, please subscribe and stay tuned! See you for the next one.

These articles will give you more details on the risks around the software supply chain and how to protect it against attacks, and around the notion of critical software developed by the NIST.