Hi Apple community,
many thanks in advance for your help.
My macOS app embeds a Python interpreter, compiled from source, including the Python executable and its associated libraries. We have tried compiling the project with Xcode 16.0 and 16.1 beta 2 over MacOS Sequoia 15.0 and 15.1
This is how the project looks like:
SampleApp.app
SampleApp.app/Contents
SampleApp.app/Contents/MacOS
SampleApp.app/Contents/MacOS/SampleApp
SampleApp.app/Contents/MacOS/bin
SampleApp.app/Contents/MacOS/bin/python3.11
SampleApp.app/Contents/Resources
SampleApp.app/Contents/Resources/lib
SampleApp.app/Contents/Resources/lib/python3.11
SampleApp.app/Contents/Resources/Info.plist
Since we want to 'initially' distribute the app directly, Python binary is signed as follows:
codesign --deep --force --options runtime --timestamp --sign "$DEVELOPER_ID_APPLICATION" "$BINARY_PATH"
App entitlements contain the next entries:
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
The resulting app is signed with entitlements, notarised and stapled. Once the app is running, we can see the next error on Console:
Prompting policy for hardened runtime; service: kTCCServiceAppleEvents requires entitlement com.apple.security.automation.apple-events but it is missing for accessing={TCCDProcess: identifier=[IDENTIFIER]], pid=58826, auid=502, euid=502, binary_path=[PATH]}, requesting={TCCDProcess: identifier=com.apple.appleeventsd, pid=824, auid=55, euid=55, binary_path=/System/Library/CoreServices/appleeventsd},
Python process is not running, we can't see any AMFI message.
Next we added to Signing and Capabilities 'Apple Events' from Hardened Runtime section. The resulting app gets signed, notarised and stapled, but when running we get only the next errors:
error 09:42:32.787744+0200 SampleApp Can't find or decode reasons
error 09:42:32.787832+0200 SampleApp Failed to get or decode unavailable reasons
Just in case it is relevant, this is how the app interacts with Python:
process.executableURL = URL(fileURLWithPath: [PATH_TO_PYTHON_BIN])
process.environment = environment
process.arguments = arguments
process.standardOutput = pipe
try process.run()
process.waitUntilExit()
We truly appreciate any guidance, help or advice. Thanks!!
I’m glad to hear you’re making progress.
This is the new entitlements:
I recommend that you remove com.apple.security.app-sandbox
.
In general, you shouldn’t add an entitlement with a value that’s the default. In this case, App Sandbox defaults to off, so you should only add the com.apple.security.app-sandbox
entitlement if you want to turn it on. Adding an entitlement with the value of false is going to cause more problems than it solves.
It appears a pop up asking 'Allow [APP] to find devices on local networks?'.
That’s almost certainly because your Python code is doing a local network operation. The correct fix for that is to stop it doing that (or accept the alert if you actually meant to do something on the local network).
For more on this, see the Local Network Privacy FAQ (I’m actively working on a full update of that for macOS, but it’s not done yet).
It’s a bit of a mystery as to why it doesn’t show up when you put the tool in Contents/MacOS/bin
. I think LNP interprets this nesting as a bundle and thus treats bin/python3.11
as an app. Now, that app isn’t really an app, and so LNP gets confused.
Regardless, this isn’t the correct fix because it’s possible that a future LNP could get past this problem and end up prompting anyway. The correct fix is to either:
-
Stop accessing the local network.
-
Or, if you actually meant to access the local network, accept that and plan accordingly.
and all libraries (*.so, *.dylib and *.a) are signed as follows:
In most cases you don’t need to sign .a
files. Indeed, in most cases you shouldn’t need to ship .a
files. I talk about this in detail in this post, and doing so can cause problems. So, unless your third-party tooling requires these .a
files to be present, I suggest you remove them.
I'm not sure if I can ask this in this thread, but I would love to distribute the app via the App Store. I already have a version available on TestFlight, but it's encountering errors when running python.
Right. Mac App Store apps must be sandboxed. Specifically:
-
Every executable in the app must be signed with the
com.apple.security.app-sandbox
entitlement. -
Executables that you spawn — that is, run as a child process using
posix_spawn
or its equivalents — must also be signed with thecom.apple.security.inherit
entitlement.
I talk about this more in Embedding a command-line tool in a sandboxed app.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"