diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml index d20bfc12..99faa6b6 100644 --- a/.github/workflows/build-app.yml +++ b/.github/workflows/build-app.yml @@ -285,12 +285,23 @@ jobs: security unlock-keychain -p "$MACOS_CERTIFICATE_PASSWORD" "$BUILD_KEYCHAIN_PATH" SIGNING_IDENTITY=$(security find-identity -v -p codesigning "$BUILD_KEYCHAIN_PATH" | awk -F '"' '{print $2}') RUNTIME_DIR="EXO.app/Contents/Resources/exo" - find "$RUNTIME_DIR" -type f \( -perm -111 -o -name "*.dylib" -o -name "*.so" \) -print0 | + RUNTIME_ENTITLEMENTS="$GITHUB_WORKSPACE/packaging/entitlements/runtime.entitlements" + + # Sign .so and .dylib files first (no entitlements needed for libraries) + find "$RUNTIME_DIR" -type f \( -name "*.dylib" -o -name "*.so" \) -print0 | while IFS= read -r -d '' file; do /usr/bin/codesign --force --timestamp --options runtime \ --sign "$SIGNING_IDENTITY" "$file" done + # Sign executables with entitlements (they load libraries via dlopen) + find "$RUNTIME_DIR" -type f -perm -111 ! -name "*.dylib" ! -name "*.so" -print0 | + while IFS= read -r -d '' file; do + /usr/bin/codesign --force --timestamp --options runtime \ + --entitlements "$RUNTIME_ENTITLEMENTS" \ + --sign "$SIGNING_IDENTITY" "$file" + done + - name: Sign, notarize, and create DMG env: MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} @@ -301,8 +312,29 @@ jobs: cd output security unlock-keychain -p "$MACOS_CERTIFICATE_PASSWORD" "$BUILD_KEYCHAIN_PATH" SIGNING_IDENTITY=$(security find-identity -v -p codesigning "$BUILD_KEYCHAIN_PATH" | awk -F '"' '{print $2}') - /usr/bin/codesign --deep --force --timestamp --options runtime \ + APP_ENTITLEMENTS="$GITHUB_WORKSPACE/app/EXO/EXO/EXO.entitlements" + + # Sign frameworks (Sparkle) inside-out + find EXO.app/Contents/Frameworks -name "*.framework" -print0 | \ + while IFS= read -r -d '' framework; do + /usr/bin/codesign --force --timestamp --options runtime \ + --sign "$SIGNING_IDENTITY" "$framework" + done + + # Sign the main app binary with entitlements (no --deep!) + /usr/bin/codesign --force --timestamp --options runtime \ + --entitlements "$APP_ENTITLEMENTS" \ + --sign "$SIGNING_IDENTITY" EXO.app/Contents/MacOS/EXO + + # Sign the outer app bundle with entitlements + /usr/bin/codesign --force --timestamp --options runtime \ + --entitlements "$APP_ENTITLEMENTS" \ --sign "$SIGNING_IDENTITY" EXO.app + + # Verify the complete signature chain + /usr/bin/codesign --verify --deep --strict --verbose=2 EXO.app + echo "Verifying entitlements are embedded:" + /usr/bin/codesign -d --entitlements - EXO.app/Contents/MacOS/EXO mkdir -p dmg-root cp -R EXO.app dmg-root/ ln -s /Applications dmg-root/Applications diff --git a/app/EXO/EXO/EXO.entitlements b/app/EXO/EXO/EXO.entitlements index 36a5baff..6e531f8a 100644 --- a/app/EXO/EXO/EXO.entitlements +++ b/app/EXO/EXO/EXO.entitlements @@ -8,5 +8,9 @@ com.apple.security.files.user-selected.read-only + com.apple.security.cs.disable-library-validation + + com.apple.security.cs.allow-unsigned-executable-memory + diff --git a/packaging/entitlements/runtime.entitlements b/packaging/entitlements/runtime.entitlements new file mode 100644 index 00000000..ed4892be --- /dev/null +++ b/packaging/entitlements/runtime.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.cs.disable-library-validation + + com.apple.security.cs.allow-unsigned-executable-memory + + +