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.
What each artifact carries
Section titled “What each artifact carries”| Artifact | Where | Signature | Build provenance | SBOM |
|---|---|---|---|---|
Images (elitea-main, elitea-web, …) | ghcr.io/elitea-ng/<image>:<version> | cosign, on the multi-arch index | On the multi-arch index | CycloneDX, one per platform image (linux/amd64, linux/arm64) |
Charts (elitea, elitea-sandbox-runtime) | oci://ghcr.io/elitea-ng/charts/<chart> | cosign | Yes | No |
| macOS desktop app | The GitHub release: Elitea_<version>_aarch64.dmg and .app.zip | Apple Developer ID, notarised and stapled | On each file | CycloneDX, 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.
Verify a signature
Section titled “Verify a signature”Stable releases and nightly pre-releases are built from main only. Pin the identity to the release workflow on main:
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.comThe 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.
Verify build provenance
Section titled “Verify build provenance”With the GitHub CLI (2.49 or later):
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/mainThe 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:
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.ymlFor the desktop app, download the file from the release and verify it by path:
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-platformWithout 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.
Read an image’s SBOM
Section titled “Read an image’s SBOM”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:
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.jsonThe 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.
Enforce it in the cluster
Section titled “Enforce it in the cluster”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/v1kind: ClusterPolicymetadata: name: elitea-signed-imagesspec: 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.devEvery 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.
What this does and does not prove
Section titled “What this does and does not prove”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.