Buildpacks which directly provide a dependency or buildpacks which install
application dependencies will support the generation of SBoM in the format of
CycloneDX and Syft. Per CNB
RFC#95, the
SBoM documents will live at <layer>.bom.<ext>.json
, launch.bom.<ext>.json
and build.bom.<ext>.json
where <ext>
will be cdx
(CycloneDX) or
syft
(Syft).
Paketo RFC#33 describes the initial strategy used to add support for SBoM generation in Paketo buildpacks. This RFC outlines the process by which Paketo buildpacks will build upon that initial strategy by including support for CycloneDX and Syft SBoM formats in accordance with the structure proposed in CNB RFC#95:SBOM.
Paketo buildpacks may produce SBoM for runtime & application dependencies in
CycloneDX and Syft formats. SBoM information may be provided in three
locations, namely <layers>/<layer>.bom.<ext>.json
, <layers>/launch.bom.<ext>.json
and
<layers>/build.bom.<ext>.json
, where is cdx
for CycloneDX or syft
for Syft
formats. The preferred content of these files is outlined below:
-
<layer>.bom.<ext>.json
: This file should be used only for SBoM information that is specific to a layer. This allows for greater specificity on the origin of the SBoM metadata, including which layer it relates to and which buildpack created the layer. Storing metadata here also potentially reduces overhead incurred by SBoM generation as the file would follow the lifecycle of the layer itself in terms caching and reuse. -
launch.bom.<ext>.json
: This file should contain SBoM entries for dependencies which are contributed to the app image, but are not necessarily scoped to a specific layer. SBoM information stored here is ephemeral and would need to be regenerated on each build. -
build.bom.<ext>.json
: This file should contain SBoM entries for dependencies which are contributed to the build environment, but are not necessarily scoped to a specific layer. SBoM information stored here is ephemeral and would need to be regenerated on each build.
Note: The above schema is not a hard requirement. What each of these files consists of is ultimately the buildpack author's decision. Additional context can be found here.
Buildpack authors will also need to specify which SBoM formats are supported by
a given buildpack via buildpack.toml
. This should look like:
api = "0.x"
[buildpack]
id = "<buildpack ID>"
name = "<buildpack name>"
# This can be an array of supported SBOM formats by the buildpack.
# Valid array values are sbom media types based on https://www.iana.org/assignments/media-types/media-types.xhtml
sbom = ["application/vnd.cyclonedx+json", "application/vnd.syft+json"]
The minimum set of Syft fields that will be initially supported is represented below. It is possible that additional fields will be supported in the future.
{
"artifacts": [
{
"id": <Syft-generated UUID string for in-file dependency graphing>,
"name": <dependency name>,
"version": <dependency version>,
"licenses": [<dependency license ID(s) in SPDX-format>],
"cpes": [<version-specific common platform enumerations>],
"purl": [<package URL per github.com/package-url>]
}
],
"descriptor": {
"name": "syft",
"version": <Syft version>
},
"schema": {
"version": "1.1.0",
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-1.1.0.json"
}
}
The minimum set of CycloneDX fields that will be initially supported is represented below. It is possible that additional fields will be supported in the future.
{
"bomFormat": "CycloneDX",
"specVersion": "1.3",
"version": <BOM revision number>,
"components": [
{
"type": <component type, usually library>,
"name": <package name>,
"version": <package version>,
"licenses": [<package license ID(s) in SPDX-format>],
"purl": <package URL per github.com/package-url>,
}
]
}
Build reproducibility is a selling point of Cloud Native Buildpacks. Since SBOMs are currently included inside OCI images built with buildpacks, if SBOMs are not reproducible, buildpack builds cannot be reproducible. It's come to our attention that the CycloneDX JSON SBOM generated by Syft includes some optional metadata that makes SBOMs irreproducible. This amendment proposes that we remove these optional metadata fields to preserve buildpack build reproducibility.
Users have brought to our attention that SBOMs in the Go buildpack broke build reproducibility, which users had been relying on. Since build reproducibility is a major value proposition of Cloud Native Buildpacks, we should not make users choose between SBOMs and reproducible builds.
As outlined on the implementation issue for this RFC, the CycloneDX v1.3 specification includes two optional pieces of metadata that result in irreproducible SBOMs. They are:
metadata.timestamp
(optional) – the time when the SBOM was generatedserialNumber
(optional) - a UUID that is intended to be unique to each SBOM; intentionally not reproducible
Since these fields are optional, this RFC proposes that we omit them both from the CycloneDX v1.3 SBOMs generated by the buildpacks.
For buildpacks that use packit
, we can omit the metadata.timestamp
and
serialNumber
fields from the Go struct that represents a CycloneDX v1.3 SBOM.
Once buildpacks upgrade to the newer version of packit
, SBOMs will no longer
include the irreproducible fields.
For buildpacks that don't use packit
, the fields can be stripped from the
SBOM JSON after it's generated, during the build process. At the time of
writing this, this is already implemented in the Java buildpacks.