Verifying signed artifacts
Every release signs its customer-facing artifacts so you can prove they came from us and haven’t been tampered with — including in an air-gapped install.
There are two kinds of artifact:
- Core container images —
query-api,ingest-gateway,enrollment,aggregator,lifecycle-manager,portal-ui, andsensor— published toghcr.io/ultrvlt/<name>. - The Helm umbrella chart — an OCI artifact at
ghcr.io/ultrvlt/charts/ultrvlt.
What each release produces
Section titled “What each release produces”| Artifact | Signature | Extra |
|---|---|---|
| Each core image | cosign key-based signature | CycloneDX SBOM + SLSA provenance attestation |
| Helm chart (OCI) | cosign key-based signature | SLSA provenance attestation |
- Key-based, not keyless. Verification needs only the published public key —
no Fulcio/Rekor, no network. This is a direct consequence of the offline-first
invariant. Signatures are made with
--tlog-upload=false, so they live in the OCI registry alongside the artifact rather than in a public transparency log. - SBOM (CycloneDX) is attached as a cosign attestation, offline-verifiable with the same key.
- SLSA build provenance is also a cosign key-based attestation
(
--type slsaprovenance), offline-verifiable with the same key. - cosign version: releases are signed with cosign v2. Verify with any
cosign ≥ v2 (v3 reworked
--tlog-uploadand would break the offline flow).
Verifying an install
Section titled “Verifying an install”Fetch the public key once, then verify offline:
export ULTRVLT_VERSION=0.1.25 # the version you're installingcurl -fsSLO https://raw.githubusercontent.com/ultrvlt/ultrvlt/main/deploy/cosign/cosign.pub
# Verify every core image you're about to run.for img in query-api ingest-gateway enrollment aggregator lifecycle-manager portal-ui sensor; do cosign verify --key cosign.pub --insecure-ignore-tlog=true \ ghcr.io/ultrvlt/$img:$ULTRVLT_VERSIONdone
# Inspect an image's SBOM.cosign verify-attestation --key cosign.pub --insecure-ignore-tlog=true \ --type cyclonedx ghcr.io/ultrvlt/query-api:$ULTRVLT_VERSION \ | jq -r '.payload | @base64d | fromjson | .predicate' > query-api.sbom.json
# Verify build provenance (offline, same key).cosign verify-attestation --key cosign.pub --insecure-ignore-tlog=true \ --type slsaprovenance ghcr.io/ultrvlt/query-api:$ULTRVLT_VERSION
# Verify the chart before installing.cosign verify --key cosign.pub --insecure-ignore-tlog=true \ ghcr.io/ultrvlt/charts/ultrvlt:$ULTRVLT_VERSIONhelm install ultrvlt oci://ghcr.io/ultrvlt/charts/ultrvlt --version $ULTRVLT_VERSIONRelease channels
Section titled “Release channels”On top of the per-version artifacts, each release publishes a channel
pointer — a small cosign-signed OCI artifact at
ghcr.io/ultrvlt/charts/ultrvlt-channels:<channel> that names the chart version
and digest a channel currently points at, plus the upgrade metadata the
lifecycle manager consumes.
latestmoves on every release.stable(the hands-off default) is promoted out-of-band from an already-released version.
Both are signed and verified with the same offline key, so channel resolution works air-gapped:
cosign verify --key cosign.pub --insecure-ignore-tlog=true \ ghcr.io/ultrvlt/charts/ultrvlt-channels:stable