Skip to content

Commit a7ecdda

Browse files
leodidoona-agent
andcommitted
fix: support SBOM generation with OCI layout export
When exportToCache is enabled, Docker images are exported in OCI layout format (image.tar) and never loaded into Docker daemon. SBOM generation was failing because it tried to inspect the Docker daemon. This fix detects OCI layout export and uses Syft's oci-archive source provider to scan the image.tar directly, enabling SBOM generation for all three formats (CycloneDX, SPDX, Syft) in SLSA L3 compliant builds. Co-authored-by: Ona <[email protected]>
1 parent 6add4dd commit a7ecdda

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

pkg/leeway/sbom.go

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -235,16 +235,41 @@ func writeSBOM(buildctx *buildContext, p *Package, builddir string) (err error)
235235
// Get the appropriate source based on package type
236236
var src source.Source
237237
if p.Type == DockerPackage {
238-
buildctx.Reporter.PackageBuildLog(p, false, []byte("Generating SBOM from Docker image\n"))
239-
240-
version, err := p.Version()
241-
if err != nil {
242-
return xerrors.Errorf("failed to get package version: %w", err)
238+
cfg, ok := p.Config.(DockerPkgConfig)
239+
if !ok {
240+
return xerrors.Errorf("package should have Docker config")
243241
}
244242

245-
src, err = syft.GetSource(context.Background(), version, nil)
246-
if err != nil {
247-
return xerrors.Errorf("failed to get Docker image source for SBOM generation: %w", err)
243+
// Check if OCI layout export is enabled
244+
if cfg.ExportToCache != nil && *cfg.ExportToCache {
245+
// OCI layout path - scan from oci-archive
246+
buildctx.Reporter.PackageBuildLog(p, false, []byte("Generating SBOM from OCI layout\n"))
247+
248+
ociLayoutPath := filepath.Join(builddir, "image.tar")
249+
if _, err := os.Stat(ociLayoutPath); err != nil {
250+
return xerrors.Errorf("OCI layout image.tar not found in %s: %w", builddir, err)
251+
}
252+
253+
// Syft will auto-detect the OCI archive format from the file path
254+
// Use explicit source provider configuration to ensure oci-archive is tried
255+
srcCfg := syft.DefaultGetSourceConfig().WithSources("oci-archive")
256+
src, err = syft.GetSource(context.Background(), ociLayoutPath, srcCfg)
257+
if err != nil {
258+
return xerrors.Errorf("failed to get OCI archive source for SBOM generation: %w", err)
259+
}
260+
} else {
261+
// Traditional Docker daemon path
262+
buildctx.Reporter.PackageBuildLog(p, false, []byte("Generating SBOM from Docker image\n"))
263+
264+
version, err := p.Version()
265+
if err != nil {
266+
return xerrors.Errorf("failed to get package version: %w", err)
267+
}
268+
269+
src, err = syft.GetSource(context.Background(), version, nil)
270+
if err != nil {
271+
return xerrors.Errorf("failed to get Docker image source for SBOM generation: %w", err)
272+
}
248273
}
249274
} else {
250275
buildctx.Reporter.PackageBuildLog(p, false, []byte("Generating SBOM from filesystem\n"))

0 commit comments

Comments
 (0)