what ships

Three things travel with every archive.

Each of the six platform archives — linux, macOS and Windows, on amd64 and arm64 — carries its own signature, certificate and SBOM, plus checksums.txt for the release as a whole, itself signed.

  • <archive>.sigstore.json — the Sigstore bundle: the cosign signature over the archive, the short-lived certificate it was signed with, and the transparency-log proof, in one file. The certificate's identity names the workflow and the tag that produced the release.
  • <archive>.sbom.json — an SPDX inventory of every Go module compiled into that binary. It has a checksum in checksums.txt like the archive itself.

Signing is keyless: there is no kute public key to distribute, rotate, or lose. The signature is bound to an ephemeral certificate issued to the release workflow's own identity and recorded in the public Rekor transparency log. What you check is who signed it — so the identity in the command below is the part that has to match.

step one

Verify the signature.

Needs cosign 3 or newer. Set the version and platform you downloaded, then fetch the archive with its bundle.

$VERSION=0.4.0
$FILE=kute_${VERSION}_linux_amd64.tar.gz
$BASE=https://github.com/kute-dev/kute/releases/download/v${VERSION}
$curl -fsSLO "${BASE}/${FILE}"
$curl -fsSLO "${BASE}/${FILE}.sigstore.json"

Then check it against the identity that signs every kute release

$cosign verify-blob \
  --certificate-identity-regexp '^https://github\.com/kute-dev/kute/\.github/workflows/release\.yml@refs/tags/' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  --bundle "${FILE}.sigstore.json" \
  "${FILE}"
success is one line Verified OK

Anything else — including a certificate whose identity doesn't match — exits non-zero. Treat that as a failed download, not a warning. On cosign 2.x add --new-bundle-format; that release reads the bundle only when asked, and cosign 3 made it the default. To pin the check to one exact release instead of any kute release, swap the regexp for the literal --certificate-identity 'https://github.com/kute-dev/kute/.github/workflows/release.yml@refs/tags/v0.4.0'.

step two

Verify what built it.

The signature says who signed the archive. Provenance says which repository, workflow, commit and runner produced it — attested by GitHub rather than by us.

$gh attestation verify --repo kute-dev/kute "${FILE}"

The two checks are independent, and worth running together: a signature with the right identity, alongside provenance naming a source commit you don't recognise, is a different kind of problem from either check simply failing.

inventory

Ask the SBOM, not us.

Every archive ships an SPDX SBOM, so "does this ship the vulnerable version of X" is a question you can answer without trusting our answer.

$curl -fsSLO "${BASE}/${FILE}.sbom.json"
$grype "sbom:${FILE}.sbom.json"

Point whichever scanner your organisation already uses at it — the SBOM is a plain SPDX inventory, not a format of ours.

already automatic

What the installers do for you.

install.sh and install.ps1 verify this signature themselves — using the same identity as above — whenever cosign is on your PATH. They always verify the checksum.

Without cosign they print a note and fall back to the checksum alone. A check nobody can run is not a stronger check — but it does mean the default one-liner install on a machine without cosign is checksum-only. If you want the strong check there, install cosign first, or follow this page by hand.

Releases published before signing landed have no .sigstore.json; the installers say so and continue. Everything from v0.4.0-beta.1 onward is signed.

A verification failure you can't explain is a security report rather than a bug report — please use GitHub's private advisory form instead of a public issue.

Install kute.

One binary, no cluster-side install. Or run kute --demo first and try it against a fake cluster.

$curl -fsSL https://kute.dev/install.sh | sh