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
+
+
+