Skip to content

Verify release binaries without requiring gh CLI authentication #2348

@frewilhelm

Description

@frewilhelm

Summary

The install script currently relies on gh attestation verify to check release artifact integrity, which requires the user to be authenticated with the GitHub CLI. If the user is not authenticated, a warning is printed but installation proceeds with an unverified binary.

We should provide a verification method that does not require authentication or a GitHub-specific tool.

Motivation

  • Security: An unauthenticated user (or a script calling the installer non-interactively) can silently end up with an unverified binary if the warning is missed.
  • OpenSSF Scorecard: Direct signature verification on release artifacts is likely required to improve the project's OpenSSF score.
  • Usability: Users should not need a GitHub token just to verify a download.

Options

Option 1: Checksums only

Generate a checksums.txt with SHA256 hashes per binary. The install script downloads it and verifies the binary hash.

  • Pros: Zero extra dependencies (sha256sum/shasum are ubiquitous). Simple to implement. This is what kubectl and Go do.
  • Cons: Verifies integrity (was the file corrupted?) but not authenticity (did it come from us?). An attacker who can tamper with the binary on GitHub Releases can also tamper with the checksums file.
  • Reference: kubernetes/kubectl install docs

Option 2: GPG detached signatures

Sign the checksums file (or each binary) with a project GPG key. Publish the public key. The install script verifies using gpg --verify.

  • Pros: gpg is pre-installed on most Linux systems. Verifies both integrity and authenticity. Well-understood, battle-tested. This is what Helm does.
  • Cons: Requires managing a GPG keypair (generation, rotation, revocation). macOS does not ship gpg by default. Helm makes signature verification opt-in for this reason (VERIFY_SIGNATURES=true).
  • Reference: helm/helm install script, Helm release assets

Option 3: Cosign keyless signing (Sigstore)

Sign the checksums file with cosign sign-blob in the release workflow using GitHub Actions OIDC identity. No private key to manage.

  • Pros: No key management. Identity tied to the GitHub Actions workflow. Transparency log provides an audit trail. This is what yq does.
  • Cons: Requires cosign binary to verify - not pre-installed anywhere. Creates a bootstrapping problem for an install script (who verifies cosign?). Effectively replaces the gh dependency with a cosign dependency.
  • Reference: mikefarah/yq release workflow

Option 4: Keep gh attestation but add checksums as fallback

Keep the current gh attestation verify path for authenticated users. Additionally generate and publish a checksums file so unauthenticated users get at least integrity verification.

  • Pros: No breaking change. Authenticated users still get full attestation. Unauthenticated users get checksums instead of nothing.
  • Cons: Does not fully solve the authenticity problem for unauthenticated users. Two code paths to maintain.

Option 5 (chosen): Just log a warning message

We will try gh attestation verify, but if that fails, the user will see a detailed message explaining how to verify binaries manually.

Comparison

Approach Extra dependency Integrity Authenticity Key management
Checksums only None Yes No None
GPG signatures gpg (usually pre-installed) Yes Yes Manual (keypair)
Cosign keyless cosign (not pre-installed) Yes Yes None (OIDC)
gh attestation (current) gh + auth token Yes Yes None (GitHub-managed)
Checksums + gh attestation fallback None / gh Yes Only if authenticated None

Implementation notes

  • The release workflow is in .github/workflows/cli-release.yml and uses a custom build step (no GoReleaser).
  • A checksums file would need to be generated during the build step (e.g. sha256sum ocm-* > checksums.txt) and uploaded as a release asset.
  • The install script lives at website/static/install.sh.

References

Metadata

Metadata

Labels

area/ipceiImportant Project of Common European Interestkind/chorechore, maintenance, etc.kind/tasksmall task, normally part of feature or epic

Type

No fields configured for Task.

Projects

Status
🍺 Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions