Hi, I’m developing a native macOS music app intended for the Mac App Store. We already support Audio Units and are investigating VST3 instrument and effect hosting on Apple Silicon. Users would install plugins themselves, typically in:
- /Library/Audio/Plug-Ins/VST3
- ~/Library/Audio/Plug-Ins/VST3
The app would load these third-party plugin bundles using public APIs, such as CFBundleLoadExecutableAndReturnError. Plugins may be signed by developers with different Team IDs. Our app would not download or install them.
Is there a supported way to load and execute these bundles while the hosting process remains sandboxed throughout? If so, which APIs and entitlements should we use?
Specifically, I’m trying to distinguish permission to read a plugin bundle from permission to load its executable code. Would user selected folder access and security scoped bookmarks cover the sandbox access requirements, or is another mechanism needed?
I understand that com.apple.security.cs.disable-library-validation addresses loading code signed by other developers, but does not itself grant sandbox file access.
We cannot rely on an Audio Unit compatibility exception that disables the host’s sandbox.
App Review Guideline 3.1.1 (https://developer.apple.com/app-store/review/guidelines/#in-app-purchase) explicitly allows Mac App Store apps to host plugins enabled outside the App Store. I’m looking for the supported technical approach under App Sandbox, rather than preapproval for our app.
We’re checking this before implementation, so we don’t yet have a failing reproducer. Any relevant documentation, sample code or existing discussion would be appreciated.
Thanks, Ben
At a technical level, I don’t see anything that stops you doing this.
If you enable the hardened runtime (which you should :-), you’ll need to disable library validation because the plug-in won’t be signed by you.
You’ll also need to dynamic extend your sandbox to allow access to the bundle, including its main executable. Typically you do that using the open panel, and persist that access using a security-scoped bookmark.
After that, use your dynamic loading API of choice (NSBundle, CFBundle, dlopen) to load the bundle’s executable and call code in it.
I prototyped this here in my office and it worked a treat. I’ve pasted in some code below.
I tested this with Xcode 26.6 on macOS 26.6.1, but I don’t think this story has changed since the very early days of the App Sandbox.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
This is the code within my bundle:
@c
func entryPoint() {
print("Hello Cruel World!")
}
Note It uses @c, as introduced by SE-0495 C compatible functions and enums, a feature that’s very welcome by me (-:
I used this to load the bundle:
let panel = NSOpenPanel()
panel.canChooseDirectories = false
panel.canChooseFiles = true
panel.allowsMultipleSelection = false
panel.allowedContentTypes = [.bundle]
panel.begin() { response in
guard
response == .OK,
let url = panel.url
else { return }
let didStart = url.startAccessingSecurityScopedResource()
defer { if didStart { url.stopAccessingSecurityScopedResource() } }
guard let b = CFBundleCreate(nil, url as NSURL) else {
print("could not create bundle")
return
}
guard CFBundleLoadExecutable(b) else {
print("could not load bundle")
return
}
guard let p = CFBundleGetFunctionPointerForName(b, "entryPoint" as NSString) else {
print("could not get function pointer")
return
}
let entryPoint = unsafeBitCast(p, to: (@convention(c) () -> Void).self)
entryPoint()
}