Skip to content

Verify release artifacts

Every Elitea release publishes evidence you can check yourself, without trusting the registry or the download page. Each artifact is signed, and each carries a signed record of how it was built (build provenance) and what is inside it (a software bill of materials, SBOM). The release workflow, .github/workflows/publish.yml, signs them with its GitHub Actions identity through Sigstore. No long-lived signing key exists to leak.

Use this page to verify an install by hand, and to configure your cluster to refuse anything that fails the check.

ArtifactWhereSignatureBuild provenanceSBOM
Images (elitea-main, elitea-web, …)ghcr.io/elitea-ng/<image>:<version>cosign, on the multi-arch indexOn the multi-arch indexCycloneDX, one per platform image (linux/amd64, linux/arm64)
Charts (elitea, elitea-sandbox-runtime)oci://ghcr.io/elitea-ng/charts/<chart>cosignYesNo
macOS desktop appThe GitHub release: Elitea_<version>_aarch64.dmg and .app.zipApple Developer ID, notarised and stapledOn each fileCycloneDX, sbom-desktop.cdx.json on the release

Build provenance follows the SLSA v1 format. It records the repository, the commit, the workflow file and the run that built the artifact. The attestations are stored in GitHub’s attestation store and pushed next to the image in the registry. Every signature is recorded in the public Sigstore transparency log, Rekor.

Every image passes a Trivy scan of its pushed digest before it is signed. A HIGH or CRITICAL finding stops the release; see Day-2 operations. The SBOMs list packages only, with no vulnerabilities. Scan them with your own tooling for today’s view: a vulnerability list frozen into a signed file would be stale the day after the release.

Stable releases and nightly pre-releases are built from main only. Pin the identity to the release workflow on main:

Terminal window
VERSION=7.3.0 # the release you install
cosign verify "ghcr.io/elitea-ng/elitea-main:${VERSION}" \
--certificate-identity "https://github.com/elitea-ng/elitea-platform/.github/workflows/publish.yml@refs/heads/main" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com

The same command verifies a chart: use ghcr.io/elitea-ng/charts/elitea:${VERSION}. A dev pre-release can be built from any branch. Its certificate names that branch, so it fails this check on purpose.

With the GitHub CLI (2.49 or later):

Terminal window
gh attestation verify "oci://ghcr.io/elitea-ng/elitea-main:${VERSION}" \
--repo elitea-ng/elitea-platform \
--signer-workflow elitea-ng/elitea-platform/.github/workflows/publish.yml \
--source-ref refs/heads/main

The command resolves the tag to its digest, then checks four things: that the attestation is signed by a Sigstore certificate GitHub issued, that the certificate belongs to the release workflow, that the workflow ran on main, and that the attestation’s subject is that digest. Add --format json to read the full SLSA predicate, including the commit (resolvedDependencies) and the run (runDetails).

A chart verifies the same way:

Terminal window
gh attestation verify "oci://ghcr.io/elitea-ng/charts/elitea:${VERSION}" \
--repo elitea-ng/elitea-platform \
--signer-workflow elitea-ng/elitea-platform/.github/workflows/publish.yml

For the desktop app, download the file from the release and verify it by path:

Terminal window
gh release download "v${VERSION}" --repo elitea-ng/elitea-platform \
--pattern "Elitea_${VERSION}_aarch64.dmg"
gh attestation verify "Elitea_${VERSION}_aarch64.dmg" --repo elitea-ng/elitea-platform

Without network access, download the trust root once with gh attestation trusted-root, and the attestation bundle with gh attestation download. Then pass both to gh attestation verify with --custom-trusted-root and --bundle.

An image SBOM is attested to the platform image, not to the multi-arch index, so it lists exactly what runs on that architecture. Resolve the platform digest first:

Terminal window
DIGEST=$(docker buildx imagetools inspect "ghcr.io/elitea-ng/elitea-main:${VERSION}" --raw \
| jq -r '.manifests[] | select(.platform.architecture == "amd64") | .digest')
gh attestation verify "oci://ghcr.io/elitea-ng/elitea-main@${DIGEST}" \
--repo elitea-ng/elitea-platform \
--predicate-type https://cyclonedx.org/bom \
--format json \
| jq '.[0].verificationResult.statement.predicate' > elitea-main-amd64.cdx.json

The output is a standard CycloneDX document. Feed it to Dependency-Track, Grype, trivy sbom or any other tool that reads CycloneDX. The desktop SBOM is also attached to the GitHub release as a plain file. It lists the crates and npm packages the app is built from: the Tauri shell, the document sidecar and the web bundle.

Verifying by hand proves one install. An admission policy proves every pod, including the ones the chart starts on an upgrade. The example below uses Kyverno (1.13 or later). It refuses any ghcr.io/elitea-ng image that the release workflow on main did not sign, and pins each one to its digest:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: elitea-signed-images
spec:
webhookConfiguration:
timeoutSeconds: 30
rules:
- name: elitea-release-signature
match:
any:
- resources:
kinds: [Pod]
verifyImages:
- imageReferences:
- "ghcr.io/elitea-ng/*"
failureAction: Enforce
mutateDigest: true
attestors:
- entries:
- keyless:
subject: "https://github.com/elitea-ng/elitea-platform/.github/workflows/publish.yml@refs/heads/main"
issuer: "https://token.actions.githubusercontent.com"
rekor:
url: https://rekor.sigstore.dev

Every image the elitea chart deploys from ghcr.io/elitea-ng is signed by that workflow. Third-party images (NATS, Qdrant, the sandbox runtime installer’s Debian base) come from other registries and are outside this rule. Cover them with their own publishers’ policies.

To enforce the build provenance as well as the signature, use the Sigstore policy-controller with GitHub’s trust root. GitHub documents the setup in Enforcing artifact attestations with a Kubernetes admission controller. Use the repository elitea-ng/elitea-platform and the workflow above as the expected identity.

A passing check proves that the artifact was built from this repository’s source, by its release workflow, on main, and that it has not changed since. It does not prove the source is free of defects. Those controls are the release’s vulnerability gate, the review every change goes through, and the settings in the Hardening checklist.