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
Summary
The install script currently relies on
gh attestation verifyto 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
Options
Option 1: Checksums only
Generate a
checksums.txtwith SHA256 hashes per binary. The install script downloads it and verifies the binary hash.sha256sum/shasumare ubiquitous). Simple to implement. This is what kubectl and Go do.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.gpgis pre-installed on most Linux systems. Verifies both integrity and authenticity. Well-understood, battle-tested. This is what Helm does.gpgby default. Helm makes signature verification opt-in for this reason (VERIFY_SIGNATURES=true).Option 3: Cosign keyless signing (Sigstore)
Sign the checksums file with
cosign sign-blobin the release workflow using GitHub Actions OIDC identity. No private key to manage.cosignbinary to verify - not pre-installed anywhere. Creates a bootstrapping problem for an install script (who verifies cosign?). Effectively replaces theghdependency with acosigndependency.Option 4: Keep
gh attestationbut add checksums as fallbackKeep the current
gh attestation verifypath for authenticated users. Additionally generate and publish a checksums file so unauthenticated users get at least integrity verification.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
gpg(usually pre-installed)cosign(not pre-installed)gh attestation(current)gh+ auth tokengh attestationfallbackghImplementation notes
.github/workflows/cli-release.ymland uses a custom build step (no GoReleaser).sha256sum ocm-* > checksums.txt) and uploaded as a release asset.website/static/install.sh.References