Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ef62327
Init
atomicturtle May 14, 2025
51ef8c3
Adding SBOM module
atomicturtle May 14, 2025
0e6adf4
Update SBOM generator plugin to v1.2.5
atomicturtle Dec 31, 2025
1994dc8
Remove legacy sbom_generator.py from root directory
atomicturtle Dec 31, 2025
2f6e049
Address PR feedback: standardize imports, logging, versioning, and docs
atomicturtle Dec 31, 2025
6425f70
Update license to GPL 2.0 or later
atomicturtle Dec 31, 2025
a851a6a
docs: Update SBOM plugin availability to 6.7
atomicturtle Jan 7, 2026
dad5c9f
feat: Refactor SBOM generator and add release notes
atomicturtle Jan 7, 2026
0710ab2
fix: Use rpm2archive instead of rpm2cpio for source extraction
atomicturtle Jan 7, 2026
9b9f662
fix: Refactor SBOM generator to use python-rpm and fix local variable…
atomicturtle Jan 7, 2026
32fba57
fix: Replace shutil.rmtree with mockbuild.file_util.rmtree for safer …
atomicturtle Jan 7, 2026
ef8c84b
fix: Use python-distro to detect chroot distribution
atomicturtle Jan 7, 2026
97f7c85
refactor: Rename _convert_to_chroot_path to from_chroot_path
atomicturtle Jan 7, 2026
03c63d3
refactor: Remove redundant special-case CPE vendor/product mappings
atomicturtle Jan 7, 2026
8308537
fix: Replace deprecated datetime.utcnow() with timezone-aware datetim…
atomicturtle Jan 7, 2026
be45f13
Lint revisions
atomicturtle Jan 29, 2026
09f0448
Minor refactors
atomicturtle Jan 29, 2026
77d45a6
SPDX option support
atomicturtle Jan 29, 2026
110dc73
Refactor: Move from_chroot_path to Buildroot class
atomicturtle Feb 25, 2026
0a1f97f
modernize metadata extraction and fix forensic grouping
atomicturtle Mar 14, 2026
e471951
QA fixes:
atomicturtle Mar 14, 2026
fee9a68
Update SBOM docs
atomicturtle Mar 14, 2026
e45e593
Update the Feature request
atomicturtle Mar 14, 2026
58c437b
Reorganize into separate files
atomicturtle Mar 27, 2026
01b4db0
Bump for build test
atomicturtle Apr 4, 2026
06ccf80
Merge upstream/main from rpm-software-management/mock
atomicturtle May 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
320 changes: 320 additions & 0 deletions docs/Plugin-SBOM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
---
layout: default
title: Plugin SBOM Generator
---

This plugin generates a Software Bill of Materials (SBOM) in CycloneDX format for packages built with Mock. The SBOM provides detailed information about the build environment, source files, and resulting packages, optimized for security use cases.

## Features

* Generates SBOM in CycloneDX 1.5 format (JSON) and SPDX 2.3 format
* Deep Chroot Integration:
* Uses the target distribution's own `rpm` binary via `doChroot` for metadata extraction, ensuring 100% version compatibility across different distributions.
* Correctly handles path mapping between chroot and host environments.
* Captures detailed information about:
* Source files and patches from spec files with a resilient regex-based fallback for legacy/strict syntax errors.
* Binary RPM metadata with standard PURL and CPE identifiers.
* Complete build toolchain packages with per-package GPG signature metadata.
* Runtime dependencies.
* File hashes (SHA-256).
* Optimized Performance: Consolidated file listing and metadata extraction into a single pass.
* Outputs SBOM in the build results directory.
* Compatible with security scanners (Grype, Trivy, Snyk).

## Usage

### Basic Usage

The simplest way to use the SBOM generator is to enable it for a single build:

```bash
# Build a package and generate SBOM
mock --enable-plugin=sbom_generator --rebuild package.src.rpm

# Or build from an existing SRPM
mock --enable-plugin=sbom_generator --rebuild ~/rpmbuild/SRPMS/package-1.0-1.fc42.src.rpm

# Specify a chroot configuration
mock --enable-plugin=sbom_generator --rebuild package.src.rpm -r rocky-9-x86_64
```

After the build completes, the SBOM will be available in the build results directory

### Viewing and Analyzing the SBOM

The generated SBOM can be analyzed using various tools:

```bash
# View basic SBOM information
jq '.metadata.component' sbom.cyclonedx.json
jq '.components | length' sbom.cyclonedx.json
jq '.dependencies | length' sbom.cyclonedx.json

# List all built packages
jq '.components[] | select(.type == "library") | {name, version, purl}' sbom.cyclonedx.json

# List source files used in the build
jq '.components[] | select(.properties[]?.name == "mock:source:type") | {name, hashes}' sbom.cyclonedx.json

# View runtime dependencies for a specific package
jq '.dependencies[] | select(.ref | contains("httpd"))' sbom.cyclonedx.json
```

### Using with Security Scanners

The SBOM can be directly used with security vulnerability scanners:

```bash

# Scan with SBOM Auditor
sbom-auditor sbom.cyclonedx.json

# Scan with Grype
grype sbom:./sbom.cyclonedx.json

# Scan with Trivy
trivy sbom sbom.cyclonedx.json

# Export to other formats if needed
syft convert sbom.cyclonedx.json -o spdx-json > sbom.spdx.json
```

## Configuration

### Enabling the Plugin

The plugin is disabled by default. You can enable it in several ways:

**Option 1: Command line (recommended for one-off builds)**
```bash
mock --enable-plugin=sbom_generator --rebuild package.src.rpm
```

**Option 2: Configuration file (for persistent enablement)**

Add to your Mock configuration file (e.g., `/etc/mock/fedora-rawhide-x86_64.cfg`):

```python
config_opts['plugin_conf']['sbom_generator_enable'] = True
config_opts['plugin_conf']['sbom_generator_opts'] = {
'generate_sbom': True
}
```

**Option 3: User configuration**

Add to `~/.config/mock/mock.cfg`:

```python
config_opts['plugin_conf']['sbom_generator_enable'] = True
```

### Configuration Options

The plugin supports several configuration options to control SBOM generation:

```python
config_opts['plugin_conf']['sbom_generator_opts'] = {
'generate_sbom': True, # Enable SBOM generation (default: True)
'include_file_components': True, # Include file-level components (default: True)
'include_file_dependencies': False, # Include file-to-package dependencies (default: False)
'include_debug_files': False, # Include debug files in file components (default: False)
'include_man_pages': True, # Include man pages in file components (default: True)
'include_toolchain_dependencies': False, # Include build toolchain in dependencies (default: False)
}
```

**Configuration Options Explained:**

- `include_file_components`: When enabled, creates individual file components for each file in built packages, including hashes, permissions, and ownership information.
- `include_file_dependencies`: Creates dependency relationships showing which files belong to which packages.
- `include_debug_files`: Filters out debug files (`.debug`, files in `/usr/lib/debug`) from file components.
- `include_man_pages`: Filters out man pages from file components.
- `include_toolchain_dependencies`: Adds build toolchain packages to the dependencies array (useful for complete build provenance, but can make dependency graphs very large).

## Output

The plugin generates a file named `<name>-<version>-<release>.sbom` (for CycloneDX) or `<name>-<version>-<release>.spdx.json` (for SPDX) in the build results directory. The SBOM includes:

* CycloneDX/SPDX document metadata
* Build timestamp
* Tool information (Mock SBOM Generator)
* Mock-specific build properties (host, distribution, chroot, config)
* RPM header metadata surfaced at the document level (buildhost, buildtime, source RPM, group, epoch, distribution, manufacture/vendor)
* Components array containing:
* Built packages (type: "library" or "application")
* Package name, version, and PURL
* CPE identifiers for vulnerability matching
* License information plus RPM summary as description
* RPM file SHA-256 hash
* Vendor, packager, buildhost, buildtime, source RPM, group, epoch, distribution metadata
* Upstream/project URLs and source RPM links via `externalReferences`
* GPG signature details
* Note: Source tarballs and patches are represented as separate file components in the components array with their own BOM refs for traceability
* Build toolchain packages (type: "library")
* All packages installed in the build environment
* Signature information
* Marked with `mock:role: "build-toolchain"` property
* Source files (type: "file")
* Source and patch files from spec
* SHA-256 hashes
* Signature information if available
* Dependencies array
* Runtime dependencies for built packages (libraries/RPMs the package depends on)
* Dependency relationships modeled using bom-refs
* Note: Source code relationships are represented in component properties and the components array, not in the dependencies section (source code is a build input, not a runtime dependency)

## Example SBOM Structure

```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:...",
"version": 1,
"metadata": {
"timestamp": "2024-01-19T15:20:00Z",
"tools": [
{
"vendor": "Mock",
"name": "mock-sbom-generator",
"version": "1.0"
}
],
"properties": [
{ "name": "mock:build:host", "value": "build.example.com" },
{ "name": "mock:build:distribution", "value": "Fedora 42" },
{ "name": "mock:build:chroot", "value": "/var/lib/mock/fedora-42-x86_64/root" },
{ "name": "mock:rpm:buildhost", "value": "builder.fedora.example.org" },
{ "name": "mock:rpm:buildtime", "value": "2024-01-19T15:15:00+00:00" },
{ "name": "mock:rpm:sourcerpm", "value": "package-name-1.0-1.fc42.src.rpm" },
{ "name": "mock:rpm:group", "value": "System Environment/Libraries" },
{ "name": "mock:rpm:epoch", "value": "1" }
],
"manufacture": {
"name": "Fedora Project"
},
"component": {
"type": "application",
"name": "package-name",
"version": "1.0-1.fc42",
"bom-ref": "build-output:package-name",
"description": "Package summary (build output containing 3 package(s))",
"licenses": [
{
"license": {
"id": "MIT"
}
}
],
"externalReferences": [
{ "type": "distribution", "url": "package-name-1.0-1.fc42.src.rpm" },
{ "type": "website", "url": "https://example.com/package-name" }
]
}
},
"components": [
{
"type": "library",
"bom-ref": "pkg:rpm/fedora/package-name@1.0-1.fc42?arch=x86_64",
"name": "package-name",
"version": "1.0-1.fc42",
"purl": "pkg:rpm/fedora/package-name@1.0-1.fc42?arch=x86_64",
"externalReferences": [
{
"type": "other",
"comment": "CPE 2.3",
"url": "cpe:2.3:a:fedora:package-name:1.0:*:*:*:*:*:*:*:*"
},
Comment thread
atomicturtle marked this conversation as resolved.
{
"type": "website",
"url": "https://src.fedoraproject.org/rpms/package-name"
},
{
"type": "distribution",
"url": "package-name-1.0-1.fc42.src.rpm"
}
],
"licenses": [
{
"license": {
"id": "MIT"
}
}
],
"hashes": [
{
"alg": "SHA-256",
"content": "..."
}
],
"properties": [
{
"name": "mock:rpm:vendor",
"value": "Fedora Project"
},
{
"name": "mock:rpm:buildhost",
"value": "builder.fedora.example.org"
},
{
"name": "mock:rpm:buildtime",
"value": "2024-01-19T15:15:00+00:00"
},
{
"name": "mock:rpm:sourcerpm",
"value": "package-name-1.0-1.fc42.src.rpm"
},
{
"name": "mock:signature:type",
"value": "GPG"
}
]
}
],
"dependencies": [
{
"ref": "pkg:rpm/fedora/package-name@1.0-1.fc42",
"dependsOn": [
"pkg:rpm/fedora/glibc@2.38-1.fc42"
]
}
]
}
```

## Security Tool Compatibility

The generated CycloneDX SBOM is compatible with popular security scanners:

* **Grype**: `grype sbom:./sbom.cyclonedx.json`
* **Trivy**: `trivy sbom sbom.cyclonedx.json`
* **Snyk**: Supports CycloneDX format for vulnerability scanning

The SBOM includes PURL (Package URL) and CPE identifiers for accurate vulnerability matching.

## Requirements

* Python 3.x
* Access to build environment for package information
* Native `rpm` and `specfile` libraries (recommended)

## Notes

* The plugin runs in the `postbuild` hook, after the build completes.
* SBOM generation is skipped if no RPM, source RPM, or spec file is found.
* **Hybrid Analysis**: Uses `doChroot` to analyze artifacts within the buildroot (ensuring compatibility with target RPM versions) and host tools for artifacts already exported to the `result/` directory.
* **Resilient Parsing**: Includes a regex-based fallback for spec files that fail strict parsing by the `specfile` library (e.g., legacy `%patchN` syntax).
* **PURL format**: `pkg:rpm/{distro}/{package}@{version}?arch={arch}`. Architecture is always separated into a qualifier, never baked into the version string.
* Mock-specific metadata is stored in properties with the `mock:` prefix.

## Competitive Advantages

This SBOM generator leverages Mock's unique build environment visibility:

* **Complete Build Toolchain**: Captures every package installed in the build chroot, not just declared dependencies
* **Build-Time Provenance**: Records the exact build environment, including tool versions and signatures
* **RPM-Native Intelligence**: Deep integration with RPM metadata, spec files, and package signatures
* **Reproducible Build Context**: Complete build environment fingerprinting for reproducibility verification

Available since version 6.7.
11 changes: 11 additions & 0 deletions mock/py/mockbuild/buildroot.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,17 @@ def make_chroot_path(self, *paths):
new_path = os.path.join(new_path, path)
return new_path

def from_chroot_path(self, host_path):
"""Convert an absolute host path into the corresponding path inside the build chroot."""
if not self.rootdir:
return host_path
if host_path.startswith(self.rootdir):
rel_path = host_path[len(self.rootdir):]
if not rel_path.startswith("/"):
rel_path = "/" + rel_path
return rel_path
return host_path

@traceLog()
def initialize(self, prebuild=False):
"""
Expand Down
12 changes: 11 additions & 1 deletion mock/py/mockbuild/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
'lvm_root', 'compress_logs', 'sign', 'pm_request',
'hw_info', 'procenv', 'showrc', 'rpkg_preprocessor',
'rpmautospec', 'buildroot_lock', 'export_buildroot_image',
'unbreq', 'expand_spec', 'system_monitor']
'unbreq', 'expand_spec', 'sbom_generator', 'system_monitor']

def nspawn_supported():
"""Detect some situations where the systemd-nspawn chroot code won't work"""
Expand Down Expand Up @@ -264,6 +264,16 @@ def setup_default_config_opts():
'expand_spec_opts': {
'rpmspec_opts': [],
},
'sbom_generator_enable': False,
'sbom_generator_opts': {
'generate_sbom': True,
'include_file_components': True,
'include_file_dependencies': False,
'include_debug_files': False,
'include_man_pages': True,
'include_source_dependencies': True,
'include_toolchain_dependencies': False,
},
'system_monitor_enable': False,
'system_monitor_opts': {
'interval' : 2
Expand Down
Loading