ci(cli): add macOS code signing with rcodesign#5675
Conversation
The released darwin binaries (Bun SFE and Go sidecar) carry only a degenerate linker-signed ad-hoc signature (CS_ADHOC | CS_LINKER_SIGNED, identifier `a.out`, no requirements blob). macOS 26/27 AMFI rejects this and SIGKILLs the process at launch (CLI-1621 / #5556). Re-sign both darwin binaries with a full ad-hoc signature in the build pipeline using rcodesign on the Linux build runner — the same signature shape `codesign --sign -` produces, requiring no Apple credentials. The signed bytes flow into every channel (npm platform packages, Homebrew, GitHub Release archives, checksums) since they all consume the same packages/cli-*/bin/ binaries. - build.ts: resolveSignMode() + signDarwinBinaries() between compile and archive; asserts the signature carries our identifier and is no longer linker-signed. SUPABASE_CLI_REQUIRE_SIGNING=1 hard-fails when rcodesign is missing; local builds warn and skip. - build-cli-artifacts.yml: install pinned rcodesign, require signing, and verify darwin signatures. - smoke-test-macos.ts + macos-signature.ts: verify signatures on the macOS smoke-test runners (ad-hoc now; Developer ID + Gatekeeper quarantine branch ready for Phase 2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GnLjngbm48rMYVwn9Guduc
Add ADR 0013 (macOS code signing & notarization) recording that ADR 0011's contingent follow-up A trigger fired, the rcodesign-on-Linux decision, the two-phase rollout, identifiers, secret names, and the no-staple rationale. Amend ADR 0011's signing row and follow-up A to point to it. Add a "Code signing (macOS)" section to release-process.md documenting the required pre-release gate: a staged dry_run release must show the macOS smoke legs green before any real cut, since signing is produced on Linux and only macOS can confirm AMFI accepts it. Note signing in binary-distribution.md's release workflow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GnLjngbm48rMYVwn9Guduc
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
…isenberg-d0cr8x # Conflicts: # .github/workflows/build-cli-artifacts.yml # apps/cli/docs/release-process.md
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase/cli/supabase@03293273a6000572200238cc925cba326cec3f19Preview package for commit |
Coly010
left a comment
There was a problem hiding this comment.
Awesome work 🎉 few things that claude highlighted just, nothing blocking though.
The CI signature check can let a mis-signed sidecar through. In the "Verify macOS signatures" step, grep -q 'identifier: com.supabase.cli' is a substring match, so it matches com.supabase.cli-go too. So if supabase-go ever got signed with com.supabase.cli by mistake, this would happily pass it — which kinda defeats the point of separate identifiers. Could we pick the expected id per binary and anchor the grep (com.supabase.cli$ vs com.supabase.cli-go$)?
signDarwinBinaries is reaching back into the module-level shell. The binary list is gated on if (shell === "legacy") reading the script-level const instead of anything passed in. Works fine today, but it's a little easy to miss, and it'll quietly need a tweak if the next shell ever gets a second sidecar. I'd just pass shell (or the resolved binary list) in as an arg so the function stands on its own.
The identifiers live in three places. MACOS_IDENTIFIERS in build.ts, EXPECTED_IDENTIFIERS in the test helper, and the hard-coded string in the workflow yaml — and nothing keeps them in sync. If one drifts we'd sign with one id and verify against another and only catch it on the macOS legs. Pulling them into one shared module that build.ts and the helper both import (and ideally pointing the CI check at the same thing) means one place to change — and it basically fixes the first point for free.
None of this blocks the actual fix though — the sign-on-Linux / verify-on-macOS approach looks solid.
Implement Phase 1 of macOS code signing to fix the SIGKILL issue on macOS 26+ (CLI-1621). The Bun SFE and Go sidecar binaries are now signed with a full ad-hoc signature during the build pipeline, replacing the degenerate linker-signed signature that AMFI rejects.
Changes
Build pipeline signing: Added
signDarwinBinaries()andresolveSignMode()toapps/cli/scripts/build.tsto sign macOS binaries (supabaseandsupabase-go) withrcodesignbetween compilation and archiving. This ensures all distribution channels (npm, Homebrew, GitHub Releases) ship the signed bytes.CI integration: Updated
.github/workflows/build-cli-artifacts.ymlto installrcodesignv0.29.0 (pinned with sha256), setSUPABASE_CLI_REQUIRE_SIGNING=1to enforce signing in release builds, and verify signatures post-build usingrcodesign print-signature-info.Smoke test verification: Extended
apps/cli/tests/smoke-test-macos.tswith native signature verification via newverifyMacSignature()helper inapps/cli/tests/helpers/macos-signature.ts. On macOS runners, this checks the signature is valid, carries the correct identifier (com.supabase.cli/com.supabase.cli-go), and is no longer linker-signed.Documentation: Added ADR 0013 documenting the decision, rationale, and Phase 2 roadmap (Developer ID + notarization). Updated
release-process.mdandbinary-distribution.mdto describe the signing step and its role in the release pipeline.Implementation details
No Apple credentials required for Phase 1: Full ad-hoc signatures are self-contained and do not require an Apple Developer ID. This fixes the SIGKILL without blocking on account provisioning.
Linux-only signing:
rcodesignruns on the existing Linux build runner, avoiding a macOS job and pipeline split. Verification happens on macOS smoke-test runners.Graceful degradation: Local builds without
rcodesignwarn and skip signing (unlessSUPABASE_CLI_REQUIRE_SIGNING=1is set), allowing contributors to build unsigned binaries for testing.Identifiers:
com.supabase.clifor the Bun SFE,com.supabase.cli-gofor the Go sidecar, configured inMACOS_IDENTIFIERSmap.See ADR 0013 for full context, Phase 2 roadmap (Developer ID + notarization), and related follow-ups (Windows Authenticode, Linux cosign).
Related #5556
https://claude.ai/code/session_01GnLjngbm48rMYVwn9Guduc