Skip to content

feat(release): sign + notarize darwin binaries, lock down release egress - #130

Open
ryanlewis wants to merge 2 commits into
mainfrom
notarize
Open

feat(release): sign + notarize darwin binaries, lock down release egress#130
ryanlewis wants to merge 2 commits into
mainfrom
notarize

Conversation

@ryanlewis

Copy link
Copy Markdown
Owner

What

  • Sign + notarize the darwin binaries via goreleaser's native notarize block (quill) — runs on the existing ubuntu-latest runner, before archiving, so tarballs/checksums/attestations all cover the signed Mach-O. wait: true means a rejected notarization fails the release before anything is published.
  • Drop the cask de-quarantine hack — Gatekeeper passes the notarized binary, including the completions-generation run at install time.
  • Preflight secret check — a missing signing secret fails the release loudly instead of silently shipping unsigned binaries with a hookless cask.
  • Egress block mode on the release job (was audit) with an explicit allowlist, since the job now holds signing keys. Shai-hulud-style exfil from a compromised dep/action is limited to the listed endpoints.
  • .github/SIGNING.md — credential setup, rotation, and leak-response runbook.

Before the next release (manual, see .github/SIGNING.md)

  • Export the Developer ID Application cert + key as a .p12 (Keychain Access); store the password
  • Create an App Store Connect API key (Developer role); note issuer ID + key ID, keep the .p8
  • gh secret set the five MACOS_* secrets into the release environment
  • Optionally cross-check the egress allowlist against the harden-runner audit reports from the v0.5.x release runs

Merging before the secrets exist is safe — the preflight step just fails any tagged release until they're in place.

Caveats

  • Bare Mach-O binaries can't be stapled; Gatekeeper does an online notarization lookup on first run (fine for brew/curl installs, only bites fully-offline first runs).
  • First notarization on a young account can be slow — notarize timeout is 30m, goreleaser --timeout raised to 60m.
  • The egress allowlist is reconstructed, not measured; if the first signed release blocks a legitimate endpoint, the harden-runner report names it — add it deliberately.

Binaries are now signed with the Developer ID Application certificate and
notarized with Apple before archiving, from the existing Linux runner (no
macOS runner needed). The Homebrew cask drops its de-quarantine preflight
hack — Gatekeeper passes the notarized binary on its own.

A preflight step fails the release if the signing secrets are absent from
the release environment, so a misconfiguration cannot silently publish
unsigned binaries; secrets are exposed to the goreleaser step only.
Credential setup, rotation, and leak response are documented in
.github/SIGNING.md.
…list

The job now holds code-signing keys, so audit-only egress monitoring is no
longer enough — block mode limits a compromised dependency or action to the
listed endpoints (GitHub, Go module proxy/toolchain, Apple notary API and
its S3 upload buckets, GitHub Sigstore for attestations).

The list is reconstructed from what each step is known to contact; the
audit reports from v0.5.x releases can confirm it before the first signed
release. A blocked legitimate endpoint shows up by name in the
harden-runner report and should be added deliberately.
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