diff --git a/docs/gaps.md b/docs/gaps.md
--- a/docs/gaps.md
+++ b/docs/gaps.md
@@ -116,8 +116,10 @@ launch #142; Linux #45, #107.
 
 ### G-05. Plugin hosting on macOS
 
-- **Missing:** the `com.apple.security.cs.disable-library-validation` entitlement in the signed
-  build, so hardened runtime refuses third-party VST3 bundles (#153, #149). AU editor views
+- **Fixed (pending release):** the `com.apple.security.cs.disable-library-validation` entitlement
+  is now in `entitlements.plist` and applied to the app and the CLI (#153, #149); verify on a
+  signed build with `codesign -d --entitlements - SoundCraft.app` and a third-party VST3.
+- **Missing:** AU editor views
   (`crates/au-host/src/lib.rs` header: "Not hosted yet: Audio Unit editor views"). Embedded CLAP
   GUIs; VST3 editors on Windows/Linux.
 - **Estimate:** ≈ 15–25 h (entitlement ≈ 1 h; AU Cocoa views and VST3 HWND/X11 views most of it).
diff --git a/docs/releasing.md b/docs/releasing.md
--- a/docs/releasing.md
+++ b/docs/releasing.md
@@ -90,8 +90,10 @@ plugins), and WebAudio in the browser.
   the default player. `NSMicrophoneUsageDescription` explains the recording prompt.
 - **Signing** goes inside-out with the hardened runtime and a secure timestamp. The executable is
   signed first, then the bundle. There's no `--deep` on the final signature. `entitlements.plist`
-  holds a single exception, `com.apple.security.device.audio-input`, without which the hardened
-  runtime blocks recording.
+  holds two exceptions: `com.apple.security.device.audio-input`, without which the hardened
+  runtime blocks recording, and `com.apple.security.cs.disable-library-validation`, without which
+  `dlopen` refuses every third-party VST3/CLAP bundle (signed by another Team ID). The CLI is signed
+  with the same entitlements because it hosts plugins too.
 - **Notarization:** the app is zipped and sent with `xcrun notarytool submit --wait`, then the
   ticket is stapled to the app. The app goes on a DMG (`hdiutil`, with an `Applications` link).
   The DMG is signed, notarized and stapled too.
diff --git a/packaging/macos/entitlements.plist b/packaging/macos/entitlements.plist
--- a/packaging/macos/entitlements.plist
+++ b/packaging/macos/entitlements.plist
@@ -1,13 +1,20 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<!-- Hardened-runtime entitlements for SoundCraft. The app is pure Rust, loads no unsigned code,
-     needs no JIT, and is not sandboxed (it opens files by path, from the command line and
-     drag-and-drop). Add exceptions here only with a reason in a comment. -->
+<!-- Hardened-runtime entitlements for SoundCraft. The app is pure Rust, needs no JIT, and is not
+     sandboxed (it opens files by path, from the command line and drag-and-drop). It does load
+     third-party plugin bundles (VST3, CLAP, AU), see below. Add exceptions here only with a
+     reason in a comment. -->
 <plist version="1.0">
 <dict>
   <!-- Recording: the hardened runtime blocks audio input (CoreAudio via cpal) without this,
        even after the user grants microphone access (NSMicrophoneUsageDescription). -->
   <key>com.apple.security.device.audio-input</key>
   <true/>
+  <!-- Plugin hosting: with library validation on, the hardened runtime only lets dlopen load
+       libraries signed by Apple or by our own Team ID, so every third-party VST3/CLAP bundle
+       fails with "dlopen failed" (#153, #149). A plugin host has to load code from other
+       vendors, so this is required. Every host DAW (Logic, Reaper, Ableton) carries it. -->
+  <key>com.apple.security.cs.disable-library-validation</key>
+  <true/>
 </dict>
 </plist>
diff --git a/packaging/macos/package.sh b/packaging/macos/package.sh
--- a/packaging/macos/package.sh
+++ b/packaging/macos/package.sh
@@ -212,7 +212,9 @@ CLI_DIR="$WORK/soundcraft-cli-$VERSION-macos-$ARCH"
 mkdir -p "$CLI_DIR"
 cp "$WORK/bin/soundcraft-cli" "$CLI_DIR/"
 copy_docs "$CLI_DIR"
-sign --options runtime "$CLI_DIR/soundcraft-cli"
+# The CLI runs the same engine and hosts plugins too, so it needs the same entitlements (the
+# library-validation exception) or third-party plugins fail to load there as well.
+sign --options runtime --entitlements "$HERE/entitlements.plist" "$CLI_DIR/soundcraft-cli"
 codesign --verify --strict --verbose=2 "$CLI_DIR/soundcraft-cli"
 rm -f "$CLI_ZIP"
 ditto -c -k --keepParent "$CLI_DIR" "$CLI_ZIP"
