sbom

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package sbom builds a Software Bill of Materials from a container image or a filesystem: it loads the image (via internal/oci), walks the flattened file tree with a set of catalogers (OS package DBs and language manifests), and serializes the result to SPDX 2.3 and CycloneDX 1.5. The same in-memory SBOM is exposed via Generate so later phases (vulnerability matching) can reuse it without rescanning. Output is deterministic: components and relationships are sorted, and the only time-varying fields (document timestamp, serial number) are injected by the caller.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DeterministicUUID

func DeterministicUUID(seed string) string

DeterministicUUID derives a stable RFC 4122-shaped UUID (version 5 layout) from a seed string, so the same input always yields the same identifier without sampling randomness or the clock.

func Marshal

func Marshal(s *SBOM, format Format, meta DocMeta) ([]byte, error)

Marshal serializes an SBOM into the requested format. The SBOM is normalized (deduplicated and sorted) first, so identical inputs yield byte-identical documents for a fixed DocMeta.

Types

type Cataloger

type Cataloger interface {
	// Name is the stable identifier recorded as Component.FoundBy.
	Name() string
	// Catalog walks the tree and returns discovered components. Distro carries
	// OS identity for building OS-package PURLs.
	Catalog(tree *oci.FileTree, d Distro) ([]Component, []Relationship, error)
}

Cataloger discovers components of one ecosystem within a file tree. Each cataloger is self-contained: it decides which files it cares about, parses them, and returns components plus any intra-ecosystem relationships it can determine (e.g. a lockfile dependency graph).

func DefaultCatalogers

func DefaultCatalogers() []Cataloger

DefaultCatalogers returns the built-in catalogers in a stable order.

type Component

type Component struct {
	Type     ComponentType `json:"type"`
	Name     string        `json:"name"`
	Version  string        `json:"version"`
	PURL     string        `json:"purl,omitempty"`
	CPEs     []string      `json:"cpes,omitempty"`
	Licenses []License     `json:"licenses,omitempty"`
	Hashes   []Hash        `json:"hashes,omitempty"`
	// Source is the file path the component was cataloged from.
	Source string `json:"source,omitempty"`
	// FoundBy is the cataloger name that produced the component.
	FoundBy string `json:"found_by,omitempty"`
}

Component is a single package or dependency discovered in the scanned artifact.

func (Component) Ref

func (c Component) Ref() string

Ref returns a deterministic, unique-enough identifier for the component, suitable as an SPDXID suffix or CycloneDX bom-ref.

type ComponentType

type ComponentType string

ComponentType classifies a component for reporting and serialization.

const (
	TypeOS      ComponentType = "operating-system"
	TypeLibrary ComponentType = "library"
	TypeApp     ComponentType = "application"
)

type Distro

type Distro struct {
	ID        string // os-release ID, e.g. "alpine", "debian", "ubuntu", "rhel"
	VersionID string // os-release VERSION_ID, e.g. "3.19.1", "11"
	Name      string // pretty name, e.g. "Alpine Linux v3.19"
}

Distro identifies the operating system of the scanned image.

func (Distro) String

func (d Distro) String() string

type DocMeta

type DocMeta struct {
	Timestamp   time.Time
	Serial      string // stable document identifier (uuid or digest-derived)
	ToolName    string
	ToolVersion string
}

DocMeta carries the document-level, time-varying fields that must be injected (rather than sampled from the ambient clock) so output stays deterministic. In tests these are set to fixed values; in production the command fills them.

type Format

type Format string

Format names a supported SBOM serialization.

const (
	FormatCycloneDX Format = "cyclonedx"
	FormatSPDX      Format = "spdx"
)

func Formats

func Formats() []Format

Formats lists the supported SBOM output formats.

type Hash

type Hash struct {
	Algorithm string `json:"algorithm"` // e.g. "SHA-256", "SHA-1", "MD5"
	Value     string `json:"value"`
}

Hash is a content digest recorded for a component.

type License

type License struct {
	// ID is an SPDX license identifier (e.g. "MIT", "GPL-2.0-only") when the
	// value maps to one; otherwise Name carries the free-text value.
	ID   string `json:"id,omitempty"`
	Name string `json:"name,omitempty"`
}

License is a detected license for a component.

type Relationship

type Relationship struct {
	From string `json:"from"` // component Ref, or "" for the document/root
	To   string `json:"to"`   // component Ref
	Type string `json:"type"` // e.g. "contains", "dependsOn"
}

Relationship links two components (or a component to the document root).

type SBOM

type SBOM struct {
	Source        Source         `json:"source"`
	Components    []Component    `json:"components"`
	Relationships []Relationship `json:"relationships,omitempty"`
	// Warnings records non-fatal cataloger problems (e.g. an rpm database in a
	// backend format not yet decodable) so callers can surface them without the
	// whole SBOM failing.
	Warnings []string `json:"warnings,omitempty"`
}

SBOM is the assembled bill of materials.

func Generate

func Generate(ctx context.Context, t *engine.Target) (*SBOM, error)

Generate builds an SBOM from an analysis target. It supports image targets (a `docker save` archive, an OCI-layout archive, or an OCI-layout directory at Target.Location) and filesystem targets (a directory at Target.Location). The operation is fully offline and deterministic. A cataloger that fails on a single ecosystem contributes a warning rather than aborting the whole SBOM, so later phases (vulnerability matching) can reuse this same entry point.

func (*SBOM) DistroNameVersion

func (s *SBOM) DistroNameVersion() (string, string)

DistroNameVersion splits Source.Distro (e.g. "alpine 3.19.1") into its distro id and version. Both are empty when no distro was detected.

type Source

type Source struct {
	Type        string `json:"type"` // "image" | "filesystem"
	Name        string `json:"name"` // image ref or path
	ImageDigest string `json:"image_digest,omitempty"`
	Distro      string `json:"distro,omitempty"` // e.g. "alpine 3.19"
}

Source describes what was scanned to produce the SBOM.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL