From 9bdc742967a3974dddf21e3da6cd9b12ddaed0f6 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Mon, 30 Mar 2026 19:24:38 -0700 Subject: [PATCH] refactor(release): improve macOS app re-signing process - Updated the re-signing workflow to strip existing signatures before signing binaries and frameworks, ensuring compliance with Apple notarization requirements. - Changed the signing approach to an inside-out method, signing nested code first and then the outer .app bundle. - Enhanced diagnostic output for better visibility during the signing process. - Updated comments for clarity on the new signing steps and their importance. --- .github/workflows/release.yml | 65 ++++++++++++++++++++++++++++++--- scripts/build-macos-signed.sh | 68 +++++++++++++++++++++++++++++++---- 2 files changed, 122 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 189d6c9dc..255a849cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -525,7 +525,7 @@ jobs: rm -f "$CERT_FILE" echo "Signing identity imported into $KEYCHAIN" - echo "=== Re-signing entire .app with hardened runtime (deep) ===" + echo "=== Re-signing .app with hardened runtime ===" # List what's inside for diagnostics echo "Contents/MacOS:" @@ -535,9 +535,66 @@ jobs: echo "Contents/Frameworks:" ls -la "$APP_PATH/Contents/Frameworks/" 2>/dev/null || echo " (none)" - # Single --deep --force pass re-signs everything atomically: - # the main binary, all sidecars, frameworks, and the outer seal. - codesign --deep --force --options runtime \ + # Step 1: Strip ALL existing signatures (tauri-action's signing may + # produce signatures that --force can't cleanly overwrite). + echo "Stripping existing signatures..." + for bin in "$APP_PATH/Contents/MacOS/"*; do + [ -f "$bin" ] && [ -x "$bin" ] || continue + echo " Stripping: $(basename "$bin")" + codesign --remove-signature "$bin" || true + done + for bin in "$APP_PATH/Contents/Resources/"openhuman-*; do + [ -f "$bin" ] || continue + echo " Stripping: $(basename "$bin")" + codesign --remove-signature "$bin" || true + done + for lib in "$APP_PATH/Contents/Frameworks/"*.dylib "$APP_PATH/Contents/Frameworks/"*.framework; do + [ -e "$lib" ] || continue + echo " Stripping: $(basename "$lib")" + codesign --remove-signature "$lib" || true + done + # Strip the bundle signature itself + codesign --remove-signature "$APP_PATH" || true + + # Step 2: Sign inside-out — nested code first, then the bundle. + MAIN_EXE="$(defaults read "$APP_PATH/Contents/Info.plist" CFBundleExecutable 2>/dev/null || echo "OpenHuman")" + echo "Main executable: $MAIN_EXE" + + # Sign frameworks/dylibs first + for lib in "$APP_PATH/Contents/Frameworks/"*.dylib "$APP_PATH/Contents/Frameworks/"*.framework; do + [ -e "$lib" ] || continue + echo " Signing framework: $(basename "$lib")" + codesign --force --options runtime \ + --sign "$APPLE_SIGNING_IDENTITY" \ + --timestamp \ + "$lib" + done + + # Sign all binaries in MacOS/ (including sidecars and main exe) + for bin in "$APP_PATH/Contents/MacOS/"*; do + [ -f "$bin" ] && [ -x "$bin" ] || continue + echo " Signing binary: $(basename "$bin")" + codesign --force --options runtime \ + --entitlements "$ENTITLEMENTS" \ + --sign "$APPLE_SIGNING_IDENTITY" \ + --timestamp \ + "$bin" + done + + # Sign sidecars in Resources/ + for bin in "$APP_PATH/Contents/Resources/"openhuman-*; do + [ -f "$bin" ] || continue + echo " Signing resource binary: $(basename "$bin")" + codesign --force --options runtime \ + --entitlements "$ENTITLEMENTS" \ + --sign "$APPLE_SIGNING_IDENTITY" \ + --timestamp \ + "$bin" + done + + # Step 3: Sign the outer .app bundle (updates the seal over everything) + echo " Signing .app bundle..." + codesign --force --options runtime \ --entitlements "$ENTITLEMENTS" \ --sign "$APPLE_SIGNING_IDENTITY" \ --timestamp \ diff --git a/scripts/build-macos-signed.sh b/scripts/build-macos-signed.sh index 371571cce..6d8d82678 100755 --- a/scripts/build-macos-signed.sh +++ b/scripts/build-macos-signed.sh @@ -155,11 +155,11 @@ fi echo echo "App bundle: $APP_PATH" -# ── Re-sign entire .app with hardened runtime (deep) ───────────────── -# Tauri signs sidecars during bundling but may not apply --options runtime -# or entitlements, which Apple notarization requires on ALL executables. -# A single --deep --force pass re-signs everything atomically: the main -# binary, all sidecars, frameworks, and the outer seal. +# ── Re-sign .app with hardened runtime (strip → inside-out) ────────── +# Tauri's signing may not apply --options runtime or entitlements to +# sidecars, which Apple notarization requires. We strip all existing +# signatures, then re-sign inside-out so the outer seal is computed +# over freshly-signed nested code. ENTITLEMENTS="app/src-tauri/entitlements.sidecar.plist" echo @@ -168,8 +168,62 @@ ls -la "$APP_PATH/Contents/MacOS/" ls -la "$APP_PATH/Contents/Frameworks/" 2>/dev/null || true echo -echo "Re-signing .app with --deep --force --options runtime..." -codesign --deep --force --options runtime \ +echo "Stripping existing signatures..." +for bin in "$APP_PATH/Contents/MacOS/"*; do + [[ -f "$bin" && -x "$bin" ]] || continue + echo " Stripping: $(basename "$bin")" + codesign --remove-signature "$bin" || true +done +for bin in "$APP_PATH/Contents/Resources/"openhuman-*; do + [[ -f "$bin" ]] || continue + echo " Stripping: $(basename "$bin")" + codesign --remove-signature "$bin" || true +done +for lib in "$APP_PATH/Contents/Frameworks/"*.dylib "$APP_PATH/Contents/Frameworks/"*.framework; do + [[ -e "$lib" ]] || continue + echo " Stripping: $(basename "$lib")" + codesign --remove-signature "$lib" || true +done +codesign --remove-signature "$APP_PATH" || true + +echo +echo "Re-signing inside-out with hardened runtime..." + +# Frameworks first +for lib in "$APP_PATH/Contents/Frameworks/"*.dylib "$APP_PATH/Contents/Frameworks/"*.framework; do + [[ -e "$lib" ]] || continue + echo " Signing framework: $(basename "$lib")" + codesign --force --options runtime \ + --sign "$APPLE_SIGNING_IDENTITY" \ + --timestamp \ + "$lib" +done + +# All binaries in MacOS/ +for bin in "$APP_PATH/Contents/MacOS/"*; do + [[ -f "$bin" && -x "$bin" ]] || continue + echo " Signing binary: $(basename "$bin")" + codesign --force --options runtime \ + --entitlements "$ENTITLEMENTS" \ + --sign "$APPLE_SIGNING_IDENTITY" \ + --timestamp \ + "$bin" +done + +# Sidecars in Resources/ +for bin in "$APP_PATH/Contents/Resources/"openhuman-*; do + [[ -f "$bin" ]] || continue + echo " Signing resource binary: $(basename "$bin")" + codesign --force --options runtime \ + --entitlements "$ENTITLEMENTS" \ + --sign "$APPLE_SIGNING_IDENTITY" \ + --timestamp \ + "$bin" +done + +# Finally, sign the outer .app bundle +echo " Signing .app bundle..." +codesign --force --options runtime \ --entitlements "$ENTITLEMENTS" \ --sign "$APPLE_SIGNING_IDENTITY" \ --timestamp \