Background
I've repeatedly run into codesigning (and missing provisioning profile) issues for my Ruby/Glimmer app and am looking for ways to troubleshoot this outside of Xcode. The app structure is as follows:
PATHmanager.app
└── Contents
├── Info.plist
├── MacOS
│ └── PATHmanager
├── PkgInfo
├── Resources
│ └── AppIcon.icns
├── _CodeSignature
│ └── CodeResources
└── embedded.provisionprofile
Architecture
I have a Mac mini Apple M2 Pro with macOS Ventura 13.4. Xcode is not used directly, but the underlying command line tools (e.g., codesign, productbuild, pkgutil, xcrun) are run from a custom Ruby script.
xcodebuild -version
Xcode 14.3.1
Build version 14E300c
Questions
-
Is the .app directory and file structure/naming sufficient? If not, can you point me in the direction of a minimal example that does not use Xcode?
-
Info.plist is an XML text document (not binary), which I believe is in an acceptable format, but how do I lint this file and determine if it contains all of the necessary key/value pairs?
<?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">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>PATH manager</string>
<key>CFBundleExecutable</key>
<string>PATHmanager</string>
<key>CFBundleIconFile</key>
<string>AppIcon.icns</string>
<key>CFBundleIdentifier</key>
<string>com.chipcastle.pathmanager</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>PATHmanager</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.15</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1.15</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
<key>LSUIElement</key>
<false/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSHumanReadableCopyright</key>
<string>© 2025 Chip Castle Dot Com, Inc.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
-
PATHmanager is a Mach-O 64-bit executable arm64 file created by using Tebako. Does this executable need to be codesigned, or is codesigning the .app folder sufficient?
-
Does the .app directory need an entitlements file? Here's how I codesign it:
codesign --deep --force --verify --verbose=4 --options runtime --timestamp --sign 'Apple Distribution: Chip Castle Dot Com, Inc. (BXN9N7MNU3)' '/Users/chip/Desktop/distribution/PATHmanager.app'
- Does the PATHmanager binary need an entitlements file? Here's how I codesign it:
codesign --deep --force --verify --verbose=4 --options runtime --timestamp --entitlements '/Users/chip/Desktop/PATHmanager.entitlements' --sign 'Apple Distribution: Chip Castle Dot Com, Inc. (BXN9N7MNU3)' '/Users/chip/Desktop/distribution/PATHmanager.app/Contents/MacOS/PATHmanager'
- How can I verify what entitlements, if any, are required for codesigning the binary? The PATHmanager.entitlements file is an XML text file containing only the following:
<?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">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
-
Is the embedded.provisionprofile necessary, and if so, how do I know determine if it matches the certificate or entitlements that I'm using? Additionally, is it named and located properly?
-
I submitted this to the AppStore several weeks ago and the reviewer reported that the executable would not load on their machine (even though it worked on mine.) Is it better for me to release via TestFlight for testing, and if so, do I need to following a separate process for codesigning (i.e., using different entitlements, profiles, certs, etc) when doing so?
I've been playing whack-a-mole with this for too long to mention and am hoping to nail down a better deployment flow, so any suggestions for improvement will be greatly appreciated. Thank you in advance.
It looks reasonable enough. A good place to start with this stuff is Placing Content in a Bundle. If you need more info then create a test project in Xcode, build it, and see what it did.
You can lint it with plutil
. Indeed, I recommend you do that.
Actually, my general advice is that you use plutil
to convert it to the XML format, which means it’s not just technically correct but in the canonical format.
It’s hard to answer that, because it depends what you app does. However, a good place to start is with the above-mentioned Xcode project.
This is answered by Creating distribution-signed code for macOS. I recommend that you follow the advice there, and in Packaging Mac software for distribution.
The file itself? No. Entitlements are baked into the program when you sign it. So you might need an .entitlements
file as an input to codesign
, but you don’t need to include that specific file in your app.
As to whether you need entitlements at all, that very much depends. See below.
Don’t use --deep
. See --deep
Considered Harmful.
There’s no single answer to that question. It depends on what your code does.
However, if you’re distributing on the App Store then, yes, you definitely need the entitlement that enables the App Sandbox.
Also, if you plan to use TestFlight, which you should, see TestFlight, Provisioning Profiles, and the Mac App Store.
Only if your app uses restricted entitlements. The App Sandox entitlement is not restricted, but the TestFlight ones are.
TN3125 Inside Code Signing: Provisioning Profiles explains that in gory detail.
This is another thing covered by Placing Content in a Bundle.
Yes. And that does complicate things somewhat, as I mentioned above.
This is good advice IMO.
You can both look at the output and also look build transcript to work out how Xcode created that output.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"