Verify your images¶
FLOWTIVO signs every image of a Tinfirm release and its Helm chart, and attaches to each image a signed list of what it contains (an SBOM). Check both before you deploy, to know that the image is the one FLOWTIVO released and that nobody changed it on its way to you: in a registry, in a mirror, or on the media that carried it into an air-gapped network.
You verify offline, with FLOWTIVO's public key alone. Nothing calls out to FLOWTIVO, to GitHub or to Sigstore's public services, so the same steps work on a machine with no route to the internet.
| Image | What it is |
|---|---|
ghcr.io/flowtivo/tinfirm-server |
The server: the web app, the REST API and the MCP endpoints |
ghcr.io/flowtivo/tinfirm-model-api |
The model port, beside LiteLLM |
oci://ghcr.io/flowtivo/charts/tinfirm |
The Helm chart, an OCI artifact; signed, without an SBOM |
What you need¶
- cosign 3.1 or later, Sigstore's command-line tool. One static binary; carry it into an air-gapped network like any other tool.
-
FLOWTIVO's public key,
cosign.pub, from https://docs.tinfirm.com/cosign.pub. Check it before you trust it, against this page and against the fingerprint FLOWTIVO sends with your contract:Check Command Expected The key's fingerprint, whatever the file's line endings openssl pkey -pubin -in cosign.pub -outform DER \| sha256sumf3aa395d8207acf829d58ad3a8d64b2d72f34af38d90ffe177fe93e912106e53The file as published sha256sum cosign.pub4c9684c54e6ae4b6f2d433070f1d616e13aeb6b8ce468e23b103187ba3b9e399The key's fingerprint is the one that counts: a file copied through a system that changes line endings has another file hash but the same key.
-
The image's digest. Verify and deploy an image by its digest (
@sha256:…), never by its tag alone: a tag can be moved to another image, a digest cannot. To read the digest a release tag names:
Verify the signature¶
cosign verify --key cosign.pub --insecure-ignore-tlog=true \
ghcr.io/flowtivo/tinfirm-server@sha256:<digest>
The command lists the checks it made and prints the signed claims as JSON. It exits with 0 only when the image carries a valid signature by the key of cosign.pub. Anything else, such as no signatures found or no matching signatures, means: do not deploy the image, and tell FLOWTIVO.
--insecure-ignore-tlog=true is expected. FLOWTIVO records no signature in Sigstore's public transparency log, so there is nothing to look up and nothing your network needs to reach. The signature is checked against cosign.pub all the same; cosign warns that it skipped the log.
Each manifest of a multi-platform image is signed too, so you can also verify the digest of one platform.
Verify the Helm chart¶
The chart of a release is signed the same way. Its version has no v: release v0.1.0 is chart 0.1.0. helm pull prints the chart's digest:
helm pull oci://ghcr.io/flowtivo/charts/tinfirm --version 0.1.0
cosign verify --key cosign.pub --insecure-ignore-tlog=true \
ghcr.io/flowtivo/charts/tinfirm@sha256:<digest>
Then install that digest, not the version alone: helm install tinfirm oci://ghcr.io/flowtivo/charts/tinfirm@sha256:<digest>. To carry the chart into an air-gapped network, use cosign save and cosign load as for the images below, then install it from your registry by the same digest.
Verify and read the SBOM¶
The SBOM is an SPDX document of every package in the image, one for each of its platforms, attached as a signed attestation:
cosign verify-attestation --key cosign.pub --insecure-ignore-tlog=true --type spdxjson \
ghcr.io/flowtivo/tinfirm-server@sha256:<digest> > attestation.json
The command checks each attestation's signature as cosign verify does, then prints the attestations, one a line. To extract the SBOM of the first one:
Feed the file to the scanner you use, such as Grype or Trivy, or to your inventory of components.
On an air-gapped network¶
Copy each image with its signatures and attestations, and verify it again inside the network. docker pull and docker push copy the image alone, without them.
-
On a machine with access to
ghcr.io, verify the image as above, then save it with what is attached to it to a directory: -
Carry the directory into the network, with
cosign.puband the cosign binary. -
Verify it from the directory, with no network at all:
-
Load it into your registry:
-
Verify it once more where your cluster pulls it from. The digest is the same as on
ghcr.io:
Then point the Helm chart or the Compose file at your registry, by digest. Do the same for tinfirm-model-api. An offline bundle of every image and update, for Enterprise, is planned; until it exists, copy the images this way.
An admission controller that verifies cosign signatures, such as Sigstore's policy-controller or Kyverno, can enforce the check in your cluster: give it cosign.pub as the key, and turn off its transparency log and certificate checks.
What is not signed¶
- The runner images. A runner host builds them itself, from the Dockerfiles in its own binary; FLOWTIVO publishes no runner image.
- The release's files: the runner host binaries and the Compose files. Check them against the release's
SHA256SUMS. - The images and charts of the development branch: images tagged
mainandsha-<commit>, charts0.0.0-sha-<commit>. They are not releases. Run a release in production.