Skip to content

kusari-oss/waybill

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

472 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Waybill

A toolkit for working with software bills of materials (SBOMs) end-to-end:

  • Generates SBOMs from source trees, package caches, and container images with lockfile-aware dep-graph extraction, emitting CycloneDX 1.6, SPDX 2.3, and SPDX 3.0.1 with SHA-256 hashes + evidence
    • real dependency relationships. On Linux, optionally captures build- time provenance via eBPF.
  • Analyzes SBOMs β€” verifies DSSE-signed attestations against keys / Fulcio identities / in-toto layouts, and cross-checks already-emitted CycloneDX / SPDX 2.3 / SPDX 3.0.1 outputs for per-datum Γ— per-format coverage parity via waybill sbom parity-check.
  • Modifies and enriches SBOMs β€” today, waybill sbom enrich applies RFC 6902 JSON Patches with provenance metadata recorded as waybill:enrichment-patch[N] properties. Richer modification workflows (license backfill, supplier resolution, VEX merging) are on the roadmap.

Waybill was previously known as Mikebom. The project was renamed in v0.1.0-alpha.66. Historical release tags (v0.1.0-alpha.7..v0.1.0-alpha.65) and pre-rename SBOMs using mikebom:* annotations remain accessible; see docs/migration/mikebom-to-waybill.md for the drop-in migration recipe.

Status: pre-1.0 alpha. The CLI surface, output formats, and per-ecosystem coverage are still being stabilized β€” expect breaking changes between alpha releases, and expect additional ecosystem readers + binary-analysis surface to keep landing release-over-release. Pre-built binaries are published as GitHub Release assets; no crates.io release yet.

  • Stable β€” waybill sbom scan, waybill sbom verify, waybill sbom enrich, waybill sbom parity-check, waybill sbom verify-binding, waybill sbom trace-binding, waybill policy init, and waybill attestation validate. Cross-platform, no special privileges.
  • Experimental, Linux-only β€” waybill trace capture / waybill trace run. eBPF-based build-time capture that produces attestations bound to the actual build event. Requires CAP_BPF + CAP_PERFMON and adds ~2–3Γ— wall-clock overhead on syscall-heavy builds.

See docs/user-guide/cli-reference.md for the per-flag operator reference and CHANGELOG.md for what shipped when.

Table of contents

Install

Pre-built binaries are published with every release as GitHub Release assets. Discover the latest tag and download:

TAG=$(gh release list -R kusari-sandbox/waybill --limit 1 --json tagName --jq '.[0].tagName')
gh release download "$TAG" -R kusari-sandbox/waybill -p "waybill-${TAG}-*-$(uname -m)-*.tar.gz"
tar -xzf waybill-*.tar.gz
sudo install -m 0755 waybill /usr/local/bin/waybill
waybill --version

Via cargo binstall (Rust toolchain users)

If you already have cargo binstall installed, you can skip the gh release download dance:

cargo binstall --git https://github.com/kusari-sandbox/waybill waybill

waybill-cli's [package.metadata.binstall] block pins the URL template to the existing release-tarball naming so discovery is deterministic. Once Waybill is published to crates.io (planned for a future milestone), bare cargo binstall waybill will work without the --git flag.

Or build from source

git clone https://github.com/kusari-sandbox/waybill.git
cd waybill
cargo build --release
# binary: ./target/release/waybill

Rust toolchain. Scan, verify, enrich, parity-check, policy, and attestation subcommands build under the stable toolchain (CI runs cargo +stable). Trace subcommands additionally need nightly for the eBPF target β€” see docs/user-guide/installation.md.

Platform support.

Platform sbom * / policy / attestation trace capture/run
Linux x86_64 βœ… supported βœ… kernel β‰₯ 5.8, CAP_BPF
Linux aarch64 βœ… supported βœ… kernel β‰₯ 5.8, CAP_BPF
macOS (Apple/Intel) βœ… supported ❌ use Lima/Docker (below)
Windows x86_64 πŸ§ͺ experimental (milestone 100, #210) ❌

On macOS, run tracing inside the waybill-dev container (Dockerfile.dev) or a Lima VM (lima.yaml). Everything else runs natively.

Windows install

πŸ§ͺ Experimental (milestone 100; runtime parity tracked in #210). Download waybill-v<version>-x86_64-pc-windows-msvc.zip from the latest release and place waybill.exe on your PATH. Known gaps and coverage details: docs/user-guide/installation.md.

First scan

waybill sbom scan --path ./my-project --output project.cdx.json

jq '.components | length, .dependencies | length' project.cdx.json

Why Waybill?

Many SBOM tools emit a flat component list with heuristic identifiers β€” good enough to eyeball, hard to build automation on. Waybill aims for SBOMs that are precise, verifiable, and self-describing. Scan-mode reads lockfiles + package manifests + per-module metadata to build a proper CycloneDX with:

  • SHA-256 content hashes on every component, from the bytes on disk.
  • Real dep-graph edges, not a flat fan-out. Per-module go.mod from the module cache drives the Go graph; Cargo.lock drives the Rust graph; for Maven there's a full layered strategy (design notes) that resolves through ~/.m2/ caches, parent POMs, BOM imports, and β€” when needed β€” deps.dev.
  • CycloneDX evidence blocks pointing back to the specific file path and parser technique that identified each component, with confidence scoring.
  • Strict PURL encoding that round-trips through the packageurl-python reference implementation (including + β†’ %2B encoding across every ecosystem; epoch=0 omission on RPM; lexicographic qualifier sort).
  • Compiled-binary identity across Linux, macOS, and Windows β€” ELF build-id, Mach-O UUID + codesign metadata, and PE pdb-id on every scanned binary, emitted symmetrically across all three output formats. Plus Go VCS provenance (commit / timestamp / dirty flag from BuildInfo), Rust crate-closure provenance (from cargo auditable builds), and curated embedded-version-string detection for 11 high-CVE-volume native libraries (OpenSSL, zlib, SQLite, curl, …) statically linked into binaries. Full reference: docs/reference/binary-identity.md.

On top of scan-mode, Waybill adds:

  • Signed DSSE envelope attestations via sigstore (local-key or keyless OIDC β†’ Fulcio β†’ Rekor).
  • In-toto layout verification for build-policy enforcement.
  • Witness-collection v0.1 output compatible with sbomit generate and any go-witness-aware verifier.

What kind of SBOM does Waybill emit?

Comparing Waybill's component count to trivy's or syft's? The gap is usually a scope choice, not a bug β€” and Waybill self-describes its scope on every output. Two orthogonal axes:

  • Document-level scope mode: artifact (on-disk components only; default for --image) vs manifest (plus declared-but-not-on-disk transitives; default for --path). Controlled by --include-declared-deps.
  • Per-component lifecycle tier: waybill:sbom-tier on every component β€” design / source / build / deployed / analyzed.

Rule of thumb: --image output β‰ˆ NTIA "deployed" SBOM; --path output β‰ˆ NTIA "build" SBOM. Full details β€” the scope tables, how each output format carries the scope natively, and the terminology bridge to other scanners β€” in docs/reference/sbom-scopes.md; the CISA SBOM-type classification and --sbom-type flag in docs/reference/sbom-types.md.

Supported ecosystems

Eleven production ecosystem readers plus a generic binary scanner. docs/ecosystems.md holds the full matrix; summary below.

Ecosystem OS package DB Lockfile / manifest Dep-graph
deb /var/lib/dpkg/status β€” Full (via Depends:)
apk /lib/apk/db/installed β€” Direct only (apk encodes no transitive)
rpm /var/lib/rpm/rpmdb.sqlite + .rpm β€” Full (via REQUIRES). BDB opt-in via --include-legacy-rpmdb.
cargo β€” Cargo.lock v3/v4 Full
gem β€” Gemfile.lock (indent-6 edges), specifications/*.gemspec Full
golang (src) β€” go.mod + go.sum + $GOMODCACHE/ Full when cache warm
golang (bin) β€” runtime/debug.BuildInfo (Go 1.18+ ELF/Mach-O/PE) Modules only (BuildInfo has no edges)
maven Fedora sidecar POMs pom.xml, embedded META-INF/maven/, ~/.m2/, deps.dev fallback Full, 5-layer resolver
npm β€” package-lock.json v2/v3, pnpm-lock.yaml, node_modules/ Full. v1 locks refused.
pip venv dist-info/METADATA poetry.lock, Pipfile.lock, requirements.txt Flat venv; tree in locks
vcpkg (102) β€” vcpkg.json (manifest mode, dependencies[] + overrides[]) Direct only
conan (102) β€” conanfile.txt ([requires]/[tool_requires]) + conanfile.py (literal requires=[...]) Direct only
generic binary β€” ELF / Mach-O / PE headers (DT_NEEDED, LC_LOAD_DYLIB, PE IMPORT) Linkage only

C/C++ build-system manifests (Bazel MODULE.bazel / WORKSPACE.bazel, CMake FetchContent_Declare / ExternalProject_Add) ship in milestone 102's second PR β€” alpha-status spec at specs/102-cpp-bazel-cmake-readers/.

Maven fat-jars built with the shade-plugin are emitted as nested components[].components[] with a waybill:shade-relocation = true property, gated on bytecode-presence verification so declared-but-not-relocated ancestors do not inflate the SBOM. See specs/009-maven-shade-deps/spec.md.

Go tip: run go build before scanning β€” with the binary present, modules the linker didn't embed get waybill:not-linked = true, giving both the broad lockfile view and a strict "what shipped" filter in one SBOM. Workflow details in docs/ecosystems.md.

Usage

# Scan a source tree (any host, no privileges; manifest scope by default)
waybill sbom scan --path ./my-project --output project.cdx.json

# Scan a container image (artifact scope; local docker cache first, registry fallback)
waybill sbom scan --image alpine:3.19 --output alpine.cdx.json

# Verify a signed DSSE attestation
waybill sbom verify some.dsse.json --public-key signer.pub

Many more recipes β€” authenticated registries, the OCI Referrers API (--sbom-source), package-cache scans, Maven fat-jar shade analysis, sbom enrich JSON patches, in-toto layouts, Kubernetes workload tagging β€” in docs/user-guide/quickstart.md. Per-flag reference: docs/user-guide/cli-reference.md.

Cross-tier correlation

When the same software produces multiple SBOMs across its lifecycle β€” source, build, and image β€” Waybill ships the identity plumbing to tie them together:

  • Stable identifiers, auto-detected (repo: from the git remote, git:<url>#<sha> at build time, image:<ref>@<digest> on image scans) and rideable by any operator-defined scheme. Credentials in remote URLs are stripped by default. See docs/reference/identifiers.md.
  • Content-addressed handshake β€” the build SBOM carries subject:sha256:X for its output binary; the image SBOM's digest matches by plain string. No Waybill-side resolver needed.
  • Explicit binding β€” --bind-to-source embeds a content-hashed reference to the source SBOM; sbom verify-binding / sbom trace-binding re-derive and walk the chain. See docs/reference/cross-tier-binding.md.
  • Per-component IDs β€” attach internal asset identifiers with --component-id <PURL>=<scheme>:<value>.

Experimental: build-time trace (Linux only)

eBPF-based capture that binds an SBOM + signed attestation to a specific build event. Requires CAP_BPF + CAP_PERFMON; ~2-3x wall-clock overhead. For most SBOM use cases prefer the scan pipeline above.

waybill trace run \
  --signing-key ./signing.key \
  --sbom-output ripgrep.cdx.json \
  --attestation-output ripgrep.attestation.dsse.json \
  -- cargo install ripgrep

# Verify from anywhere (verify is pure-scan, works on macOS):
waybill sbom verify ripgrep.attestation.dsse.json --public-key ./signing.pub

Keyless (Fulcio/Rekor) flows, policy layouts, and the witness-v0.1 format: docs/architecture/signing.md, docs/architecture/attestations.md.

Documentation

  • User guide β€” installation, quickstart, CLI reference, configuration.
  • Architecture β€” four-stage pipeline (scan β†’ resolve β†’ enrich β†’ generate), PURL & CPE emission rules, license resolution, in-toto attestation schema.
  • Ecosystems β€” per-ecosystem coverage matrix (authoritative).
  • SBOM scopes reference β€” artifact vs manifest scope, lifecycle tiers, terminology bridge to other scanners.
  • Binary identity reference β€” ELF/Mach-O/PE identity annotations, Go VCS provenance, cargo-auditable closures, embedded-version-string detection.
  • Identifiers reference β€” the four built-in schemes, auto-detection rules, per-format wire carriers, decode recipes for external consumers.
  • SBOM types reference β€” CISA Design / Source / Build / Analyzed / Deployed / Runtime classification, per-format jq recipes, and the --sbom-type <type> operator-assert flag.
  • Cross-tier binding reference β€” --bind-to-source schema, verifier protocol, multi-tier trace flows.
  • SBOM format mapping β€” per-feature carrier matrix across CDX 1.6, SPDX 2.3, and SPDX 3.
  • Conformance harness guide β€” for external implementers writing cross-format conformance suites.
  • Design notes β€” living architectural decisions at the cross-cutting level.
  • Changelog β€” what shipped in which release.
  • Specs β€” per-milestone planning specs (001 build-trace pipeline β†’ 076 subject + per-component identifiers).

Workspace layout

waybill-cli/      User-space CLI: scan, resolve, enrich, generate, verify, trace
waybill-common/   Shared types: PURL, attestation schema, resolution types
waybill-ebpf/     Kernel-side eBPF probes (uprobe on libssl, kprobe on file ops)
xtask/            Workspace build/dev tooling
docs/             User guide, architecture, ecosystems, design notes
specs/            Per-milestone planning specs
tests/fixtures/   Real + synthetic fixtures consumed by integration tests

Reporting issues and contributing

Open an issue or PR at github.com/kusari-sandbox/waybill. CI enforces cargo +stable clippy --workspace --all-targets and cargo +stable test --workspace on every PR; run both locally before opening one.

License

Apache-2.0. See the workspace Cargo.toml for the declared license field.

Releases

Packages

Contributors

Languages