Software Bill Of Materials
View SourceSoftware Bill-of-Materials (SBOM)
A Software Bill-of-Materials (SBOM) is a document to share information about the software used, dependencies and, essentially, what the software is made of. SBOMs have many different use cases, and some examples include verification of licenses, or vulnerability scanning using databases such as CVE and OSV, among others.
Erlang/OTP has multiple third-party dependencies. Some are vendored into the source code of Erlang/OTP:
- pcre2 (
erts/emulator/pcre) - zlib (
erts/emulator/zlib) - asmjit (
erts/emulator/asmjit) - openssl (
erts/emulator/openssl) - zstd (
erts/emulator/zstd) - others
The Erlang/OTP project provides source SBOMs starting with OTP 28. Below we detail structure of the source SBOM.
Source SBOM Structure And General Understanding
Erlang/OTP publishes a source SBOM for Erlang/OTP using SPDX v2.2 format. The source SBOM can be seen as a tree data structure.
root: the root of the tree is found under the keydocumentDescribes. The value is a single item that points to the SPDXpackagethat represents the root node from where all packages converge. This root node contains mostly configuration files that do not belong to Erlang/OTP applications nor runtime applications. All SPDX packages (Erlang/OTP apps and runtime, explained later) are under thepackageskey in the SPDX document.{ "SPDXID": "SPDXRef-DOCUMENT", "creationInfo": { ... }, "dataLicense": "CC0-1.0", "documentDescribes": [ "SPDXRef-Project-OTP" ], <----- ROOT NODE ..., "name": "Erlang/OTP", "packages": [ { "SPDXID": "SPDXRef-Project-OTP", <----- DESCRIPTION OF ROOT NODE "downloadLocation": "https://github.com/erlang/otp/releases", "externalRefs": [ { "comment": "", "referenceCategory": "PACKAGE-MANAGER", "referenceLocator": "pkg:github/erlang/otp@28.0.1", "referenceType": "purl" } ], "filesAnalyzed": true, "hasFiles": [ "SPDXRef-File-1", "SPDXRef-File-2", ...] <----- FILES IN ROOT NODE }, ... <----- OTHER PACKAGES LIKE ERTS ] }First level branches from
rootrepresent Erlang/OTP applications, the runtime system (erts), and some vendor build scripts (SPDXRef-otp-make-install-sh). As an example, we show below theertspackage.{ "SPDXID": "SPDXRef-otp-erts", "downloadLocation": "https://github.com/erlang/otp/releases", "externalRefs": [ { "comment": "Erlang Runtime System", "referenceCategory": "PACKAGE-MANAGER", "referenceLocator": "pkg:otp/erts@16.0.1?vcs_url=git+https://github.com/erlang/otp.git", "referenceType": "purl"}], ... "filesAnalyzed": true, "hasFiles": [ "SPDXRef-File-380", ...], "name": "erts", "packageVerificationCode": { "packageVerificationCodeValue": "2568c51ee8756f36b6173037035ca4f77ed0d00b" }, "supplier": "Organization: Ericsson AB", "versionInfo": "16.0.1" },All Erlang/OTP application SPDX packages are named with the prefix
SPDXRef-otp-<appname>.<appname>represents the name of an Erlang application, where the value is the name of the Erlang application with the underscores_dropped, e.g.,common_testbecomescommontest.Application packages have at least two sub packages. One for tests and one for docs.
The documentation and the tests packages add a suffix to the
SPDXRef-otp-<appname>, namelydocumentationandtest. We usestdlibas a running example to explain the package structure in the SPDX SBOM, where Erlang/OTP applications:SPDXRef-otp-stdlib-documentationcontains all documentation aboutstdlib, andSPDXRef-otp-stdlib-testcontains all tests aboutstdlib, andSPDXRef-otp-stdlibcontains the source code of thestdlibapplication.
{ "SPDXID": "SPDXRef-otp-stdlib", <------- stdlib PACKAGE "downloadLocation": "https://github.com/erlang/otp/releases", "externalRefs": [...], "filesAnalyzed": true, "hasFiles": [ "SPDXRef-File-9022", "SPDXRef-File-9023", ... ], "name": "stdlib", "packageVerificationCode": { "packageVerificationCodeValue": "29200c1cd7da4a5c015cdafd6f71db538ae0a1c9" }, "supplier": "Organization: Ericsson AB", "versionInfo": "7.0.2" }, { "SPDXID": "SPDXRef-otp-stdlib-documentation", <------- stdlib DOCUMENTATION PACKAGE ... "name": "stdlib-documentation", "packageVerificationCode": { "packageVerificationCodeValue": "ad443de0ca77bf6cbadc35813e0807494949f25c" }, "supplier": "Organization: Ericsson AB", "versionInfo": "7.0.2" }, { "SPDXID": "SPDXRef-otp-stdlib-test", <------- stdlib TEST PACKAGE ... }Application packages have the following fields:
namewhich represents the Erlang/OTP application name, e.g.,stdlib,erts, etc, and/or the application name with the suffixdocumentationortest, e.g.,stdlib-testandstdlib-documentation.copyrightTextincludes the copyright of all the files under the given package.downloadLocationspecifies where the package can be downloaded from.versionInfospecifies the version of the application, which in case of documentation or test packages, it refers to the top-level application. For example, thestdlibpackage hasversionInfoequals to7.0.2and its correspondingstdlib-documentationandstdlib-testpackages will have the sameversionInfo, as this is the version of the package.licenseInfoFromFilescontains the list of licenses found in the files that belong to the given package.- for other clarications, please check the SPDX 2.2 standard.
The application package, application test package, and the application documentation package may all in turn contain one or more vendor packages. An example of this is the package
SPDXRef-otp-ertswho contains other packages, such asSPDXRef-otp-erts-asmjit.To remove non-needed applications from your SBOM, remove the first level packages (Erlang/OTP applications) that are not needed, including all of their transitive dependencies (other packages reachable from them), as well as all files reachable from these packages. For example, to remove the application
ftp, one must remove the packageSPDXRef-otp-ftp,SPDXRef-otp-ftp-documentation, andSPDXRef-otp-ftp-test, and all the files that they reference (including also relationship items). In most ocassions, you may want to remove the first level Erlang/OTP applications and the keep first level vendor dependencies (identified by comment "vendor package" in the SPDX package). The reason for keeping the first level vendor dependencies is that those include Erlang/OTP building scripts.
Below we show how the stdlib packages are linked between them and against the root package, "SPDXRef-Project-OTP".
In this particular case, stdlib does not have any more relationships. But Erlang/OTP applications have dependencies
in their app.src file and these are also captured in the source SBOM in the relationships field. If you remove packages,
you need to remove relationships that do not exist anymore.
{
"SPDXID": "SPDXRef-DOCUMENT",
"creationInfo": { ... },
"dataLicense": "CC0-1.0",
"documentDescribes": [ "SPDXRef-Project-OTP" ], <----- ROOT NODE
...,
"name": "Erlang/OTP",
"packages": [ ... ],
"relationships": [ <----- RELATIONSHIPS, OR, HOW EVERYTHING FITS TOGETHER
{
"relatedSpdxElement": "SPDXRef-otp-stdlib",
"relationshipType": "TEST_OF", <----- THESE ARE TESTS
"spdxElementId": "SPDXRef-otp-stdlib-test"
},
{
"relatedSpdxElement": "SPDXRef-otp-stdlib",
"relationshipType": "DOCUMENTATION_OF", <----- THESE ARE DOCUMENTS, EXAMPLES, ETC
"spdxElementId": "SPDXRef-otp-stdlib-documentation"
},
{
"relatedSpdxElement": "SPDXRef-Project-OTP",
"relationshipType": "PACKAGE_OF", <------ THIS SPECIFIES THAT stdlib IS PART OF PROJECT-OTP
"spdxElementId": "SPDXRef-otp-stdlib"
},
...
]
}Verification Of Source SBOM
In each release, Erlang/OTP releases a source SBOM together with a signed SBOM attestation artifact. This gives users the ability to verify the signed artefact.
Below we show how to do this for Erlang/OTP version 28.0.2 using Sigstore cosign (installation) and/or Github gh tools (installation).
Sigstore cosign
Download the SBOM for
28.0.2, namedbom.spdx.json(here)Download the sigstore file,
bom.spdx.json.sigstore(here)Run
cosignwith the following parameterscosign verify-blob-attestation \ --bundle "bom.spdx.json.sigstore" \ --new-bundle-format \ --type "https://spdx.dev/Document/v2.2" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ --certificate-identity "https://github.com/erlang/otp/.github/workflows/main.yaml@refs/tags/OTP-28.0.2" \ "bom.spdx.json"
Github CLI gh
Download the SBOM for
28.0.2, namedbom.spdx.json(here)Run
ghwith the following parametersgh attestation verify \ --predicate-type "https://spdx.dev/Document/v2.2" \ --repo "erlang/otp" \ --source-ref "refs/tags/OTP-28.0.2" \ "bom.spdx.json"