Skip to content

Sign the installer download with minisign#12

Merged
REPPL merged 2 commits into
mainfrom
security/installer-minisign
Jul 18, 2026
Merged

Sign the installer download with minisign#12
REPPL merged 2 commits into
mainfrom
security/installer-minisign

Conversation

@REPPL

@REPPL REPPL commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Now that the repo is public, install.sh is a real distribution path for
arbitrary users, and it previously trusted the release download on TLS alone
(then stripped the Gatekeeper quarantine). This adds end-to-end signature
verification.

What changes

  • release.yml: signs SHA256SUMS.txt with minisign using a key held only in
    the MINISIGN_SECRET_KEY CI secret, and attaches SHA256SUMS.txt +
    SHA256SUMS.txt.minisig to the Release. Fails closed if the secret is unset.
  • install.sh: carries the matching public key, downloads the checksums +
    signature, verifies the signature (minisign -V), then confirms the
    downloaded asset's SHA-256 matches — all before unpacking, clearing
    quarantine, or copying into /Applications. Any failure aborts. Requires
    minisign (clear message → brew install minisign).
  • The baked-in public key is a placeholder until signing is set up; the
    installer refuses to run rather than silently skip verification.
  • README: documents the minisign requirement and the trust model.

The exact sign/verify command pair was smoke-tested locally with minisign 0.12:
a valid signature verifies, a tampered SHA256SUMS.txt is rejected (exit 1),
and shasum -c --ignore-missing handles verifying just the one downloaded app.

⚠️ Do NOT merge until signing is wired up, in this order

Merging this to main before a signed release exists will break the install
one-liner for everyone (it will refuse the current unsigned latest release).
Sequence:

  1. Generate a passwordless keypair locally:
    minisign -G -W -p minisign.pub -s minisign.key
  2. Add the private key as a repo secret:
    gh secret set MINISIGN_SECRET_KEY < minisign.key
  3. Paste the second line of minisign.pub (the RW… string) into
    MINISIGN_PUBKEY in install.sh on this branch, replacing the placeholder.
    Commit. Keep minisign.key out of git.
  4. Cut/re-run a release so a signed SHA256SUMS.txt is published to latest.
  5. Only then merge this PR.

Assisted-by: Claude:claude-fable-5

REPPL added 2 commits July 18, 2026 09:25
Now that the repo is public, install.sh is a real distribution path, and it
previously trusted the release download on TLS alone. It now verifies a
minisign signature over the release checksums before unpacking the app,
clearing its quarantine, or copying it into /Applications:

- release.yml signs SHA256SUMS.txt with a key held only in the
  MINISIGN_SECRET_KEY CI secret and attaches the .minisig to the Release.
  The step fails closed if the secret is unset.
- install.sh carries the matching public key, fetches the checksums + sig,
  verifies the signature (minisign -V), then confirms the downloaded asset's
  SHA-256 matches. Any failure aborts before install. minisign is required;
  a clear message points to `brew install minisign`.
- The public key is a placeholder until signing is set up; install.sh
  refuses to run rather than silently skip verification.
- Quarantine is now stripped only after cryptographic verification, so that
  step is justified rather than a blind trust.

The exact sign/verify commands were smoke-tested locally with minisign 0.12:
a valid signature verifies, a tampered checksums file is rejected (exit 1).

One-time setup for the maintainer is documented at the top of install.sh
(generate a passwordless keypair, add the secret, paste the public key).

Assisted-by: Claude:claude-fable-5
Replaces the placeholder with the public half of the release signing key.
The private half lives only in the MINISIGN_SECRET_KEY CI secret.

Assisted-by: Claude:claude-fable-5
@REPPL
REPPL merged commit 9922ed7 into main Jul 18, 2026
1 check passed
@REPPL
REPPL deleted the security/installer-minisign branch July 18, 2026 09:13
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.

1 participant