Multiple Executables in a Single Bundle Fails to Launch Others After Codesign

We have a rather complex network of dependencies for our application stack and, from it, we create multiple unique executables that are placed into the Contents/MacOS directory of our bundle.

MyApp.app
`- Contents/
`- Frameworks/...
`- MacOS/
`- exec_a
`- exec_b
`- Resources/...

Both executables require the same dependencies (and use the same shared .dylib files built as targets in the same project) so it makes sense for them to be in the same place rather than in their own .app folder as I understand it.

Qt Libs -> core_lib.dylib -> gui_lib.dylib -> exec_a
`-> exec_b

etc.

We've confirmed build artifacts are correct and the rpath/dependencies are all clean. When in development, all executables run as expected and we can command exec_a (the executable we're listing in the primary Info.plist) to launch exec_b at any time.

Once the bundle is signed, however, we cannot get exec_b to launch in any capacity. Even lldb dies right away because it can't attach to anything. We assume this is something in the gatekeeper area of blocking these additional executables.

We get the following when trying to run those additional exes in any way:

Trace/BPT trap: 5

We're using macdeployqt to finalize the bundle and bring in the correct packages - perhaps something it's doing is causing the additional executables to fail or we're missing an entitlement.

We've submitted the app to TestFlights successfully even with these invalid executables to see if there was something the processing of the app would find but so far nothing.

We've seen other example of applications with multiple executables in the same MacOS directory and are wondering what the difference is. Any hints or guidance would be great. Thank you!

Answered by DTS Engineer in 831614022

It should be possible to get this setup working.

You mentioned TestFlight, which suggests you’re targeting the Mac App Store. If so, all your executables must be sandboxed. If you plan to spawn exec_a as a child process of exec_b then exec_b has to use sandbox inheritance. See Resolving App Sandbox Inheritance Problems.

The other potential gotcha is entitlements. If exec_a uses restricted entitlements [1] then those entitlements get authorised by the provisioning profile embedded in the app bundle. If exec_b also needs restricted entitlements then things get trickier. So, does exec_b need any restricted entitlements?

A restricted entitlement is one that must be authorised by a profile, as explained in TN3125 Inside Code Signing: Provisioning Profiles.

Finally, I have a bunch of hints and tips on this topic in Resolving Trusted Execution Problems.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Which it’ll need for a TestFlight deployment, as explained in •.

It should be possible to get this setup working.

You mentioned TestFlight, which suggests you’re targeting the Mac App Store. If so, all your executables must be sandboxed. If you plan to spawn exec_a as a child process of exec_b then exec_b has to use sandbox inheritance. See Resolving App Sandbox Inheritance Problems.

The other potential gotcha is entitlements. If exec_a uses restricted entitlements [1] then those entitlements get authorised by the provisioning profile embedded in the app bundle. If exec_b also needs restricted entitlements then things get trickier. So, does exec_b need any restricted entitlements?

A restricted entitlement is one that must be authorised by a profile, as explained in TN3125 Inside Code Signing: Provisioning Profiles.

Finally, I have a bunch of hints and tips on this topic in Resolving Trusted Execution Problems.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Which it’ll need for a TestFlight deployment, as explained in •.

Quinn! Thank you for your efforts and details. Your posts on this forum have been a lifesaver for those of us new to the world of Apple development/deployment.

Current Entitlements

Each of our executables require the same entitlements:

  • com.apple.security.app-sandbox
  • com.apple.security.cs.disable-library-validation
  • com.apple.security.files.user-selected.read-write
  • com.apple.security.network.client
  • com.apple.security.network.server

From the research into the articles you posted, it seems like these are all safe to inherit but I could be wrong about that! And if it's all going to TestFlight then I suppose it's restricted? The lib validation is disabled because we include a plugin ecosystem through Qt.

I've tried adding the com.apple.security.inherit in our entitlements but am still seeing the same issue.

Here's the entitlements for the exec_b (and exec_a)

> codesign -d --entitlements - exec_b
Executable=/Users/foo/src/SomeApp.app/Contents/MacOS/exec_b
[Dict]
[Key] com.apple.security.app-sandbox
[Value]
[Bool] true
[Key] com.apple.security.cs.disable-library-validation
[Value]
[Bool] true
[Key] com.apple.security.files.user-selected.read-write
[Value]
[Bool] true
[Key] com.apple.security.inherit
[Value]
[Bool] true
[Key] com.apple.security.network.client
[Value]
[Bool] true
[Key] com.apple.security.network.server
[Value]
[Bool] true

Syslog

I then moved through the Console.app and found that, upon launching the errant executable from the command line, this form of error is logged:

Unable to get bundle identifier for container id exec_b: Unable to get bundle identifier because Info.plist from code signature information has no value for kCFBundleIdentifierKey.

I assume this is due to trying to launch the non-default application in the bundle. Is there any means of spelling out this is a valid application without a snarly bundle and symlink web?

Cheers

Written by mmccartney in 831680022
Each of our executables require the same entitlements:

This is potentially confusing, so let’s go to a table:

Entitlement App Child
----------- --- -----
….app-sandbox true true
….inherit - true
….cs.disable-library-validation true true
….files.user-selected.read-write true -
….network.client true -
….network.server true -

In this table:

  • App is your main application and Child is any program is spawns as a child process.

  • - indicates that the entitlement shouldn’t be claimed at all. In general, you shouldn’t claim an entitlement with a false value, that just causes confusion.

For the last three rows, you don’t need to, and mustn’t claim, the entitlement because these are part of your static sandboxed, which is what the second row is about.

Written by mmccartney in 831680022
And if it's all going to TestFlight then I suppose it's restricted?

None of the above entitlements are restricted.

To deploy to TestFlight you’ll need to:

  • Add com.apple.application-identifier and com.apple.developer.team-identifier to your App.

  • Embed a profile in your App.

That should be sufficient given your current setup. The Child programs don’t need their own App ID because they don’t claim any restricted entitlements. If they did, things would get more complex.

See TestFlight, Provisioning Profiles, and the Mac App Store for more about the TestFlight side of this.

Written by mmccartney in 831680022
I then moved through the Console.app and found that, upon launching the errant executable from the command line

Right. Because Terminal has no sandbox, and thus there’s nothing for com.apple.security.inherit to inherit. When embedding a tool in a Mac App Store app, you must apply com.apple.security.app-sandbox. After that you have a stark choice:

  • If you want to spawn that tool as a child process of your app, apply com.apple.security.inherit. Such tools can’t be executed from Terminal.

  • If you want to run the tool some other way, don’t apply com.apple.security.inherit. You won’t be able spawn the tool as a child process of your app. Rather, it’ll start with its own sandbox.

My understanding is that you only care about the first case. If so, we’re done. If you need the second case as well, lemme know because there are further steps necessary.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Getting back to this! Thanks again or the detailed response.

The ugly truth is we need exec_b to be run from exec_a and by thirdparty tools that might need to call up it's UI.

Think of exec_a as a sort of launcher program that orchestrates exec_b instances it's called up but so too do other parts of our pipeline, potentially.

Written by DTS Engineer in 831858022
Add com.apple.application-identifier and com.apple.developer.team-identifier to your App.

Where should this be put? In the entitlements.plist we use while signing App?

If we're to test the .inherit entitlement to just get exec_a launching exec_b, you're describing something like:

# codesign other binaries... (macdeployqt does much of this work)
# Sign child exec
codesign ... --entitlements=./entitle_child.plist .../exec_b
# Then sign the App (including the com.apple.application... tags)
codesign ... --entitlements=./entitle_app.plist .../App.app

Apologies if I'm missing the mark here. App validation like this is a bit out of my wheelhouse and everything feels like a crash course at the moment.

Extra Detail

It's worth noting that we've submitted to TestFlight Internal well enough with each of the applications as their own app (e.g. exec_a is the primary executable in ExecA.app, exec_b in ExecB.app, etc.) without the additional entitlement changes. We've had users run and test those programs on their own.

Does this mean the com.apple.application-identifier and other entitlement are purely for getting these extra executables to function?

Attempting to test this embedded profile and just getting more lost it seems.

After changing the entitlements for exec_a (based on the App.app bundle) to:

com.apple.application-identifier
com.apple.developer.team-identifier
com.apple.security.app-sandbox
com.apple.security.cs.disable-library-validation
com.apple.security.files.user-selected.read-write
com.apple.security.network.client
com.apple.security.network.server

Where the value of the first is: <teamid>.com.<company>.<app> that matches the format we're expecting. And the team-identifier is <teamid> that matches our team. I've gone mad quadruple checking the values line up as expected based on your other posts on this forum.

The exec_b entitlements are:

com.apple.security.app-sandbox
com.apple.security.cs.disable-library-validation
com.apple.security.inherit

Of which is based on the table you posted above. We then built manual profiles for both a Mac App Store and macOS Development profile that includes the cert that we're signing these things with.

I've tried embedding either profile (one at a time) into the Contents folder as described in one of you posts and I fail to get results from either of them. Once done we can't launch anything anyone (I assume because of the bad profile/mixup of entitlements).

With the embedded profile in the Contents directory we get an error in Console.app like:

Only Development Provisioning Profiles can be installed in System Settings. Production Provisioning Profiles are imported within Xcode

Perhaps this is because we're trying to run things not delivered by the Mac Store yet. It's confusing and unclear at each step.

If I take out the profile, downloading them manually through Xcode, Console.app is giving us:

Unsatisfied entitlements: com.apple.developer.team-identifier

We're crashing and burning here.

Written by mmccartney in 833266022
Perhaps this is because we're trying to run things not delivered by the Mac Store yet.

If you’re trying to run a distribution-signed app then, yeah, that won’t work. See Don’t Run App Store Distribution-Signed Code.

However, it seems like you were also testing development-signed app and that’s also failing.


I tried your setup from Xcode, just to make sure that I wasn’t completely misleading you. AFAICT everything worked as expected. Here’s what I did:

  1. Using Xcode 16.3 on macOS 15.3.2, I created a new app from the macOS > App template.

  2. I then ran through the instructions in Embedding a command-line tool in a sandboxed app to create a new helper tool target and embed the results.

  3. I added a button that launched it:

    Button("Spawn") {
    do {
    print("will launch")
    let p = Process()
    let u = Bundle.main.url(forAuxiliaryExecutable: "ToolX")!
    p.executableURL = u
    try p.run()
    print("did launch")
    } catch {
    print("did not launch, error: \(error)")
    }
    }
  4. In both the app and the tool target, I set Hardened Runtime > Disable Library validation.

  5. In the app, I added the Custom Network Protocol capability. This uses a restricted entitlement, which forces Xcode to allocate an App ID and generate a profile for it.

  6. I ran the app using Product > Run and clicked the button, just to make sure it works.

  7. I chose Product > Archive.

  8. In the Xcode organiser, I selected the new archive, clicked the Distribute App button, and then followed the Debugging workflow.

  9. I ran the exported app from the Finder and it continues to work as expected.

Here’s what that app looks like:

% find Test778169.app
Test778169.app
Test778169.app/Contents
Test778169.app/Contents/_CodeSignature
Test778169.app/Contents/_CodeSignature/CodeResources
Test778169.app/Contents/MacOS
Test778169.app/Contents/MacOS/Test778169
Test778169.app/Contents/MacOS/ToolX
Test778169.app/Contents/Resources
Test778169.app/Contents/embedded.provisionprofile
Test778169.app/Contents/Info.plist
Test778169.app/Contents/PkgInfo

And here’s its entitlements:

% codesign -d --entitlements - Test778169.app
[Dict]
[Key] com.apple.application-identifier
[Value]
[String] SKMME9E2Y8.com.example.apple-samplecode.Test778169
[Key] com.apple.developer.networking.custom-protocol
[Value]
[Bool] true
[Key] com.apple.developer.team-identifier
[Value]
[String] SKMME9E2Y8
[Key] com.apple.security.app-sandbox
[Value]
[Bool] true
[Key] com.apple.security.cs.disable-library-validation
[Value]
[Bool] true
[Key] com.apple.security.files.user-selected.read-only
[Value]
[Bool] true
% codesign -d --entitlements - Test778169.app/Contents/MacOS/ToolX
[Dict]
[Key] com.apple.security.app-sandbox
[Value]
[Bool] true
[Key] com.apple.security.cs.disable-library-validation
[Value]
[Bool] true
[Key] com.apple.security.inherit
[Value]
[Bool] true

As you can see, this matches what you’re trying to achieve.

Finally, here’s the profile:

% security cms -D -i Test778169.app/Contents/embedded.provisionprofile | plutil -p -
{
"DeveloperCertificates" => [
0 => {length = 1480, bytes = 0x308205c4 308204ac a0030201 02021067 ... 4c66a803 c77a58b8 }
]
"Entitlements" => {
"com.apple.application-identifier" => "SKMME9E2Y8.com.example.apple-samplecode.Test778169"
"com.apple.developer.networking.custom-protocol" => 1
"com.apple.developer.team-identifier" => "SKMME9E2Y8"
"keychain-access-groups" => [
0 => "SKMME9E2Y8.*"
]
}
"ProvisionedDevices" => [
0 => "00008103-0002091E3C62001E"
]
}

As you can see, it’s a development profile [1] and it has an allow list that covers all the restricted entitlements claimed by the app.

Note If you’re not familiar with the insides of a provisioning profile, see TN3125 Inside Code Signing: Provisioning Profiles.

[1] Because the ProvisionedDevices property limits it to certain devices.


I’m not sure why this is failing for you. Well, I understand why this fails when you use a distribution profile, but not when you use a development profile.

My general procedure for debugging problems like this is to create a working example using Xcode and then have my custom build process do what Xcode did. If you run through the process I described above, can you get it work?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Multiple Executables in a Single Bundle Fails to Launch Others After Codesign
 
 
Q