Release Supply-Chain Verification¶
Hubuum stable releases publish verifiable native archives and multi-platform
container images. Release evidence is tied to the tagged source commit and is
created only after the tagged commit has passed the blocking main workflow.
Dependency policy¶
deny.toml is the committed Rust dependency policy. It checks RustSec
advisories, yanked packages, licenses, trusted registries, exact git revisions,
and duplicate versions of selected security-critical TLS and cryptography
crates. The same policy runs for relevant pull requests, main, release tags,
and the daily scheduled supply-chain workflow.
Run the policy locally with:
Supply-chain exceptions are deny-by-default. An advisory, license, or container
vulnerability exception must be present in both the tool-specific policy and
.github/supply-chain-exceptions.json. Each metadata entry requires a reason,
owner, and ISO 8601 expiry date. CI rejects expired or unmatched entries.
An exception has this shape:
{
"kind": "container-vulnerability",
"id": "CVE-YYYY-NNNN",
"reason": "Scanner false positive confirmed against the shipped package",
"owner": "@hubuum/security",
"expires": "2026-09-01"
}
Immutable build inputs¶
GitHub Actions are pinned to full commit SHAs with their readable release name
in a comment. CI service images and release tooling containers are pinned by
OCI digest. .github/supply-chain-tools.env records exact versions and image
digests for cargo-deny, cargo-semver-checks, Diesel CLI, Syft, Trivy, and
cosign. Consumers read individual validated values rather than evaluating the
manifest as shell code.
Diesel CLI, cargo-deny, and cargo-semver-checks are built from checksum-verified crates.io sources at exact versions. The semantic checker is installed only when a workspace package is deliberately classified as public. Syft and Trivy run from digest-pinned OCI images. The pinned cosign installer verifies the downloaded executable before use. Workflows record the executable or platform-image digest and tool version in their run summary.
Validate these controls locally with Python 3.11 or newer
selected as python3 on PATH:
python3 scripts/check-supply-chain-policy.py
python3 tests/python/run.py unit policies.test_supply_chain
bash scripts/test-generate-container-evidence.sh
bash scripts/test-generate-release-sbom.sh
Native release evidence¶
Every stable native archive has a neighboring CycloneDX 1.6 SBOM named
<archive>.cdx.json. The SBOM identifies the archive digest, source revision,
release tag, build target, exact Cargo feature selection, Cargo lockfile digest,
workspace crates, and target-filtered resolved Rust dependencies.
release-checksums.txt is the authoritative SHA-256 manifest for all native
archives and their SBOMs. It is signed keylessly with Sigstore and published
with its release-checksums.sigstore.json verification bundle. GitHub also
publishes SLSA build provenance for every digest in that manifest. The release
includes the provenance bundle, detailed build-input predicate, and its signed
attestation bundle.
Download and verify a release without maintainer secrets:
version=v0.0.9
gh release download "$version" --repo hubuum/hubuum --dir "hubuum-$version"
cd "hubuum-$version"
sha256sum --check release-checksums.txt
cosign verify-blob \
--bundle release-checksums.sigstore.json \
--certificate-identity "https://github.com/hubuum/hubuum/.github/workflows/ci.yml@refs/tags/$version" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
release-checksums.txt
gh attestation verify \
"hubuum-linux-x86_64-all-features-$version.tar.gz" \
--repo hubuum/hubuum
Choose the archive matching the operator platform in the final command. Inspect
its neighboring .cdx.json file before deployment when dependency inventory is
part of the local approval process.
Container evidence and signatures¶
Each stable platform image receives a CycloneDX SBOM containing both Syft's final Alpine package inventory and Cargo's resolved Rust dependency graph. The SBOM and SLSA provenance are attached as signed GitHub attestations to the platform-image digest. The final multi-architecture manifest is separately attested and signed keylessly with cosign. Versioned tags that resolve to the same manifest share that immutable signature.
Verify the final manifest and its GitHub provenance:
version=v0.0.9
image=ghcr.io/hubuum/hubuum-server
digest="$(docker buildx imagetools inspect \
--format '{{json .Manifest}}' "$image:$version" | jq --raw-output '.digest')"
cosign verify \
--certificate-identity "https://github.com/hubuum/hubuum/.github/workflows/ci.yml@refs/tags/$version" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
"$image@$digest"
gh attestation verify \
"oci://$image@$digest" \
--repo hubuum/hubuum
Platform SBOM attestations can be retrieved and verified with the platform
digest shown by docker buildx imagetools inspect --raw:
gh attestation verify \
"oci://ghcr.io/hubuum/hubuum-server@sha256:PLATFORM_DIGEST" \
--repo hubuum/hubuum \
--predicate-type https://cyclonedx.org/bom \
--format json
Final-image vulnerability policy¶
The digest actually pushed for each AMD64 and ARM64 release platform is scanned with a digest-pinned Trivy image. Both operating-system and application-library packages are included. A fixed HIGH or CRITICAL vulnerability blocks the final multi-architecture release manifest. Unfixed findings are retained in the full JSON report but do not block publication because no deployable remediation is available.
Syft generates the container SBOM and Trivy independently scans both the final image and that SBOM. The merged SBOM, raw Syft inventory, Trivy image report, fixed-finding policy report, Trivy SBOM report, scan status, and signed attestation bundles are retained as workflow artifacts for 90 days. Signed OCI attestations and container signatures remain attached to the immutable release digest.
A scanner false positive must not be suppressed inline. Add the exact advisory
identifier to .trivyignore and matching time-bounded metadata to
.github/supply-chain-exceptions.json; CI enforces the pairing and expiry.
Mutable main artifacts are development builds. Main container images receive
SBOMs and final-image scans, but their moving tags are not represented as
stable signed releases.