Best Practices 🔗
- Automate the generation of your SBOM, e.g., by including its generation in your CI/CD pipeline.
- Include metadata about your software in the SBOM, in addition to including at least:
- The name of your company, including your company website and a contact.
- The git hash of the source code used to generate the file.
- The timestamp when the SBOM was generated.
- A short description of the component.
- Include all the fields from Framing Software Component Transparency: Establishing a Common Software Bill of Materials (SBOM) in your SBOM.
- Use a tool to continuously monitor for vulnerabilities in the SBOM for all devices in the field.
- Include a PDF version of your SBOM with your regulatory submissions.
- Have a process for periodically reviewing the identified vulnerabilities and systematically evaluating their risk to patient safety.
Basics 🔗
What is an SBOM? 🔗
An SBOM, or Software Bill of Materials, is a comprehensive list of components, libraries, and dependencies used in a software system.
What is the purpose of an SBOM? 🔗
SBOMs provide transparency about the software's composition, making it easier to track and manage potential vulnerabilities, licensing requirements, and other risks associated with software usage. An SBOM can include information about open-source and commercial components, as well as their respective versions and licensing information.
Do we need to include an SBOM in our 510(k) submission? 🔗
If your medical-device has the ability to connect to the internet and has “any such technological characteristics … that could be vulnerable to cybersecurity threats,” then you need an SBOM.
This is true since March 2023. See here for more details.
Does the FDA have any other expectations for what an SBOM should contain? 🔗
We’ve had the FDA request improvements to submitted SBOMs, so merely including an SBOM is not sufficient in and of itself. The FDA has asked that submitted SBOMs follow industry best practices or standards and they have referenced the NTIA’s document, Framing Software Component Transparency: Establishing a Common Software Bill of Materials (SBOM), which was published in October 2021. We’ve had the FDA request that the Baseline Software Component Information (e.g., Supplier Name; Component Name; Unique Identifier (UID); Version String; Component Hash; Relationship; and Author Name) from the NTIA document be included.
Note that the FDA’s draft guidance recommends that quite a bit of information be included for each component in the SBOM. We feel that, in most cases, it’s not worth the effort to include all of this information. We believe the primary use case for SBOMs is vulnerability monitoring, which can be accomplished without all of the additional requested information. Thus, we suggest including only enough information to accomplish this main use case.
Generating an SBOM 🔗
How do we create an SBOM? 🔗
The basic process involves these steps:
- Select an SBOM file-format.
- Identify the third-party components, libraries, and dependencies used in, or to produce, your software.
- Gather the information needed to fill in the required attributes for your SBOM format.
- Insert the information into your SBOM file.
- Validate your SBOM file.
We suggest automating the process and incorporating it into your CI/CD pipeline.
Usually some components are not tracked anywhere else and need to be manually added.
What SBOM file format should we use? 🔗
There are three widely-used SBOM formats:
- SPDX
- CycloneDX
- SWID
We recommend the CycloneDX format. It has good tooling support and it’s specification is short and more developer friendly. (Compare it to the SPDX specification.) The CycloneDX format is focused on security use-cases while the SPDX historically focused on open-source license tracking.
That said, some tools (e.g., GitHub) produce SPDX files, and it is also industry standard.
The SWID format is a proprietary standard that costs $225 (as of June 2022), so we didn’t consider using it, primarily due to the annoyance of buying and distributing a paid standards PDF.
If you’d like a more in-depth comparison of the formats, the 2021 Survey of Existing SBOM Formats and Standards is a good read.
Can we upload a machine-readable SBOM in our regulatory submissions? 🔗
Yes, the FDA’s new eSTAR format allows for machine-readable attachments. However, as of 2023 the FDA has been asking for human-readable (e.g., a PDF or Excel file) versions of the SBOM as well. JSON doesn’t cut it.
How do you create a human-readable SBOM? 🔗
TODO: Fill in some details about how to do this here.
What components should be included in our SBOM? 🔗
The conservative answer is that any other software that’s used in the creation of your software (and thus may introduce vulnerabilities into your software) should be included.
This list may include:
- System dependencies (e.g., Python v3.10.3)
- Language dependencies (e.g., Tensorflow v2.9.1)
- Dependencies of your language dependencies (e.g., if package A depends on package B, be sure to include package B too.)
- The operating system
- Compilers
- Continuous integration services
- SaaS services your system depends on
- and more.
Keeping up with all of these dependencies takes a lot of effort. Thus, given limited resources we suggest focusing on dependencies that are higher risk. This typically means the components that are directly incorporated into your software, but not tooling used to produce the software.
Is it okay to have multiple SBOMs? 🔗
It would be preferable to have one SBOM to give to your customers and to the FDA. You can often merge SBOMs together. For example, using cyclonedx-cli. Consider using a hierarchical merge when appropriate.
How do you automate the generation of an SBOM? 🔗
There is a growing suite of tools you can use to automate your SBOM generation process.
GitHub supports generating SBOMs automatically.
Tools like Syft can generate SBOMs from container images or filesystems.
There are also “lower-level” tools that operate on a language-level. For example, if you have Python language dependencies, you can import them from your requirements.txt
file.
How do you identify individual software components for your SBOM? 🔗
A key part of the SBOM formats is the component identifier. This identifier allows the entries in the SBOM to be checked against various vulnerability databases. Therefore, it’s important that the identifiers be correct, otherwise vulnerability monitoring tools won’t be effective.
So says the NTIA Multistakeholder Process on Software Component Transparency
Framing Working Group, in their 2021 Software Identification Challenges and Guidance.
Perhaps the biggest single challenge to supply chain transparency and the Software Bill of Materials (SBOM) model is identifying software components with sufficient discoverability and uniqueness.
The CycloneDX format supports a few identification mechanisms for identifying components, however, when it comes to identifying known vulnerabilities, the CycloneDX website makes the following comment (emphasis ours):
Identifying known vulnerabilities in components can be achieved through the use of three fields:
cpe
,swid
, andpurl
. Not all fields apply to all types of components. The CPE specification was designed for operating systems, applications, and hardware devices. CPE is maintained by the NVD and has been deprecated [it’s unclear that this is true, see here]. Software ID (SWID) as defined in ISO/IEC 19770-2:2015 is used primarily to identify installed software and is the preferred format of the NVD. Package URL (PURL) standardizes how software package metadata is represented so that packages can universally be located regardless of what vendor, project, or ecosystem the packages belongs.Components that have a cpe, swid, or purl defined can be analyzed for known vulnerabilities.
Guidelines
USE RECOMMENDATION Client or Server Application CPE or SWID Container PURL or SWID Firmware CPE or SWID Library or Framework (package) PURL Library or Framework (non-package) SWID Operating System CPE or SWID Operating System Package PURL or SWID Not all sources of vulnerability intelligence support all three fields. Use of multiple sources may be required to obtain accurate and actionable results.
For language dependencies, often the PURL identification is the only mechanism possible. For example, see this comment by the Python Packaging Working Group:
As you consider SWID in particular, please bear in mind that it only applies to some kinds of software and would need to be supplemented by other identifier schemes to cover other categories; for example, we believe it would not be viable to assign an SWID for every package on PyPI. Please also look into PURL, which attempts to cover that lacuna.
How do you look up a PURL identifier? 🔗
First, familiarize yourself with package URL (purl). See here for some examples.
Then, look up the purl package type that’s applicable to you. Here are all of the types as of 2022:
bitbucket
for Bitbucket-based packagescocoapods
for Cocoapodscargo
for Rustcomposer
for Composer PHP packagesconan
for Conan C/C++ packagesconda
for Conda packagescran
for CRAN R packagesdeb
for Debian, Debian derivatives, and Ubuntu packagesdocker
for Docker imagesgem
for Rubygemsgeneric
for plain, generic packages that do not fit anywhere elsegithub
for Github-based packagesgolang
for Go packageshackage
for Haskell packageshex
for Hex packagesmaven
for Maven JARs and related artifactsnpm
for Node NPM packagesnuget
for NuGet .NET packagesoci
for all artifacts stored in registries that conform to the OCI Distribution Specificationpub
for Dart and Flutter packagespypi
for Python packagesrpm
for RPMsswift
for Swift packages
For the appropriate URL as specified there.
How do you look up a CPE identifier? 🔗
You can learn more about CPE identifiers here. (If you’re really curious, the full spec is here.)
To search for a CPE identifier, download the archives here and use a text searching tool (like ripgrep) to search through the files. It usually takes some digging.
Note that CPE identifiers are only added for software that has a known vulnerability. Thus, you may occasionally find a CPE identifier for one version of your component but not for the version you are using. In these cases, we recommend following the format of the CPE identifier and swapping out the version or year as appropriate.
How do you look up a SWID identifier? 🔗
We’re not sure how to do this.
Do you have any other resources for learning about SBOMs? 🔗
Yes! Here are a few more good reads:
- How-To Guide for SBOM Generation
- Framing Software Component Transparency: Establishing a Common Software Bill of Materials (SBOM)
- 2021 Software Identification Challenges and Guidance
- 2021 Survey of Existing SBOM Formats and Standards
Vulnerability Monitoring 🔗
Do we need to do monitor our SBOM for vulnerabilities? 🔗
Yes, you must
design, develop, and maintain processes and procedures to provide a reasonable assurance that the device and related systems are cybersecure, and make available postmarket updates and patches to the device and related systems to address—(A) on a reasonably justified regular cycle, known unacceptable vulnerabilities; and (B) as soon as possible out of cycle, critical vulnerabilities that could cause uncontrolled risks.
Thus, you need some mechanism to scan your SBOM for known vulnerabilities.
What are good tools for finding vulnerabilities using an SBOM? 🔗
GitHub’s Dependabot may be used in certain cases, although as of April 2023 it only supports certain package ecosystems.
Another tool to consider is the free and open-source Dependency Track.
Black Duck and Snyk are good paid options to consider.
Will the FDA scan our SBOM? 🔗
We haven’t seen any evidence of the FDA doing this, but it wouldn’t surprise us if they start doing this. The FDA does expect that you have evaluated the safety risk associated with any known vulnerabilities. One approach is to list the known vulnerabilities alongside your Unresolved Software Anomalies.
Examples 🔗
The following examples show how to handle some common situations with SBOM generation when using CycloneDX. Note that the examples are not valid standalone SBOMs since they do not include some mandatory metadata, such as the bomFormat
, speVersion
, or version
.
Your Device 🔗
It’s helpful to include the name and version of your medical device software in the SBOM metadata so that it’s easy to identify which version of your software the SBOM applies to. This information goes inside the metadata.component
field. See here for details. Here’s an example that includes other metadata suggested by the NTIA:
{
"metadata": {
"timestamp": "2060-06-09T00:33:20+0000",
"authors": {
"name": "Medical Device Manufacturer Name",
"url": "https://yourwebsite.com"
},
"supplier": {
"name": "Medical Device Manufacturer Name"
"url": "https://yourwebsite.com"
},
"component": {
"type": "application",
"name": "Medical Device Name",
"author": "Medical Device Manufacturer Name",
"version": "1.0.5"
}
},
}
The 2013 Visual C++ Redistributable Package 🔗
The Visual C++ Redistributable Package is not included in any of the purl types, so we searched the CPE database for it. We found match for the Visual Studio 2017 runtime, but the 2013 runtime was not present. Thus, we copied the CPE identifier for the 2017 runtime and updated the year number as a best guess attempt at identifying this dependency. The “name” field is a best guess based on the CPE string. The “type” is set to “library” despite the fact that the CPE identifier begins with “a” (for application). This is because the runtime isn’t really an application.
{
"components": [
{
"type": "library",
"name": "visual_studio",
"cpe": "cpe:2.3:a:microsoft:visual_studio:2013:-:*:*:*:*:*:*"
}
]
}
Python 🔗
None of the purl package types apply to Python itself, thus the CPE identifier was used. A few searches of the CPE database turned up a match. This can be included as a CycloneDX component as follows:
{
"components": [
{
"type": "application",
"name": "python",
"cpe": "cpe:/a:python:python:3.6"
}
]
}
This article was originally published on June 2, 2022. It was updated on June 7, 2023 to reflect the newest FDA regulations and guidance, and particularly section 524B(b)(3) of the FD&C Act.