This guide walks through setting up Witness to instrument your build, then using SBOMit to generate an enriched SBOM from the resulting attestation.
Prerequisites
Part 1: Witness
Witness wraps your build process and records signed attestations, a cryptographic audit trail.
1. Install Witness
bash <(curl -s https://raw.githubusercontent.com/in-toto/witness/main/install-witness.sh)
Or download a binary from the Witness releases page.
2. Create a signing keypair
Witness signs each attestation with a private key. For a quick local test:
openssl genpkey -algorithm ed25519 -outform PEM -out testkey.pem
openssl pkey -in testkey.pem -pubout > testpub.pem
Tip: Witness also supports keyless signing via SPIRE/SPIFFE and Sigstore Fulcio for CI/CD environments.
3. Configure Witness
Create a .witness.yaml in your project root. This file is typically committed alongside your
public key:
# .witness.yaml
run:
signer-file-key-path: testkey.pem
trace: false
verify:
attestations:
- "attestation.json"
policy: policy-signed.json
publickey: testpub.pem
Command-line flags override config file values. Run witness help to see all options.
4. Wrap your build
Prefix your build command with witness run to produce an attestation file:
witness run --step build -o attestation.json -- <your-build-command>
Go project:
witness run --step build -o attestation.json -- go build -o myapp .
Python project:
witness run --step build -o attestation.json -- pip install -r requirements.txt
Witness always runs a base set of
attestors — see witness attestors list for the full list.
Tip: For builds that produce many files (e.g.
node_modules), use--dirhash-glob node_modules/*to hash the directory contents rather than every individual file.
5. Inspect the attestation
The attestation file is a signed DSSE envelope. To view the payload:
cat attestation.json | jq -r .payload | base64 -d | jq
You will see an attestation collection containing typed attestations: material, command-run,
product, environment, and optionally network-trace. This is the data SBOMit uses.
Part 2: SBOMit
With an attestation file in hand, SBOMit generates an enriched SBOM by running language-specific package resolvers over the build data Witness observed.
1. Install SBOMit
go install github.com/sbomit/sbomit@latest
2. Generate an enriched SBOM
# SPDX 2.3 (default)
sbomit generate attestation.json
# SPDX 2.2
sbomit generate attestation.json -f spdx22
# CycloneDX 1.5
sbomit generate attestation.json -f cdx15
# CycloneDX 1.4
sbomit generate attestation.json -f cdx14
3. (Optional) –catalog to Capture Dependency Tree
SBOMit can call Syft as an additional catalog source, merging its output with the attestation-derived data:
sbomit generate attestation.json --catalog syft --project-dir /path/to/project
SBOMit(right now) produces a flat list of dependencies, it knows what was installed and used, but does not reconstruct the full dependency tree. Syft, for ecosystems where it can resolve the tree structure (e.g. Go modules, npm), preserves that parent-child relationship in its output.
By passing --catalog syft, SBOMit uses Syft’s dependency tree as the foundation and
then complements it with everything Syft cannot see: the actual versions installed at build time,
native libraries, files not tracked by any package manager, and network call provenance captured
by Witness.