Skip to content

feat(release): sign checksums with cosign keyless and verify in install.sh and cora upgrade (#591) - #637

Merged
ajianaz merged 2 commits into
developfrom
feat/cosign-release-signing-591
Oct 9, 2026
Merged

ajianaz merged 2 commits into
developfrom
feat/cosign-release-signing-591

Conversation

@ajianaz

@ajianaz ajianaz commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

What

  • release.yml (release job): installs cosign (sigstore/cosign-installer v3.10.1 pinned by SHA, cosign v2.6.5), signs checksums-sha256.txt keyless with cosign sign-blob --yes --bundle, immediately re-verifies it against the workflow identity, then creates the release. checksums-sha256.txt.sigstore.json is uploaded with the other assets (files: release-artifacts/*). id-token: write is added to that job only (alongside contents: write).
  • install.sh: after the checksums download, fetches the bundle (same curl limits, 1 MiB cap) and runs cosign verify-blob with identity regexp ^https://github.com/codecoradev/cora-code/\.github/workflows/release\.yml@refs/tags/v and issuer https://token.actions.githubusercontent.com.
  • cora upgrade: same policy in Rust. It shells out to cosign (no Sigstore crate), with pure functions for URL, identity and policy and a CosignRunner trait as the process seam.
  • CORA_REQUIRE_SIGNATURE=1 makes a missing cosign or bundle fatal. Unknown values are an error, and combining it with the checksum skip env vars is rejected, so a requested verification is never silently dropped.
  • Docs: docs/installation.md (manual verify, policy matrix, scope), SECURITY.md, README, CHANGELOG ### Security, AGENT.md post-release checklist.
  • scripts/test_install_signature.sh: stub-based decision-matrix test for install.sh.

Design note: signing happens in the same job, before the release step. If signing or verification fails, the job stops and no release is created, so there is no half-published release. One signature over the checksums covers all four archives.

Policy matrix (install.sh and cora upgrade):

Bundle cosign Default REQUIRE=1
present, valid yes install install
present, invalid yes abort abort
present no install + notice abort
404 (old release) any install + notice abort
other download error any abort abort

Why

Checksums come from the same release as the archive, so a compromised release defeats them (#580 follow-up). Keyless signing ties the checksums to this repo's release workflow without any long-lived key to manage.

Testing

  • cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test (3 runs; 1121 lib tests pass). tests/brain_search_process failed once in one of the three full runs and passed when rerun alone; it does not touch this change.
  • sh -n install.sh; sh scripts/test_install_signature.sh (fake curl/cosign: verified, cosign rejects, cosign missing, bundle 404, REQUIRE=1 variants, HTTP 500, network error, invalid env, cosign flags).
  • Rust unit tests for the policy matrix, env parsing, URL and identity constants (no network, temp dirs only).
  • release.yml parsed with yaml.safe_load; actionlint, shellcheck and cosign were not available locally. A keyless signature cannot be produced locally, so the end-to-end path is untested until a real tag.

What to check on the next release:

  1. The release job's "Install cosign", "Sign checksums" and "Verify the fresh signature" steps are green (OIDC permission accepted, no id-token error).
  2. The release has checksums-sha256.txt.sigstore.json next to checksums-sha256.txt.
  3. Manual cosign verify-blob (command in docs/installation.md) succeeds against the published files, with cosign 2.x and 3.x.
  4. CORA_REQUIRE_SIGNATURE=1 CORA_VERSION=vX.Y.Z sh install.sh installs; the same without cosign on PATH aborts; without the env var it prints the checksum-only notice.
  5. CORA_REQUIRE_SIGNATURE=1 cora upgrade --yes from the previous version works (the older binary has no signature check; test it from this release onward).
  6. A previous unsigned release still installs with a notice.

Closes #591

🤖 Generated with Claude Code

ajianaz and others added 2 commits October 9, 2026 13:48
…ll.sh and cora upgrade (#591)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@ajianaz
ajianaz merged commit deaf938 into develop Oct 9, 2026
14 checks passed
@ajianaz
ajianaz deleted the feat/cosign-release-signing-591 branch October 16, 2026 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

security(release): sign release artifacts (cosign or minisign) and verify in install.sh / cora upgrade

1 participant