Postinstall fails to run binary in ./scripts

Hi,

When postinstall tries to run another binary inside the ./scripts folder I package with pkgbuild, it gets killed by taskgated when the postinstall script tries to run it.

└── Contents
    ├── Helpers
    ├── Info.plist
    ├── MacOS
    │   ├── UI
    │   └──Worker
    ├── PkgInfo
    ├── Resources
    │   ├── com.ui.plist
    │   ├── com.worker.plist
    │   └── icon.icns
    ├── _CodeSignature
    │   └── CodeResources
    └── embedded.provisionprofile

scripts:

├── token_installer
├── postinstall

├── token_installer ├── postinstall

How I am signing:

codesign --entitlements entitlements.plist --timestamp --options=runtime --sign "$DEVELOPER_ID" --force out/myapp.app/Contents/MacOS/UI
codesign --entitlements entitlements.plist --timestamp --options=runtime --sign "$DEVELOPER_ID" --force out/myapp.app/Contents/MacOS/Worker
codesign --entitlements entitlements.plist --timestamp --options=runtime --sign "$DEVELOPER_ID" --force ./scripts/token_installer
codesign --entitlements entitlements.plist --timestamp --options=runtime --sign "$DEVELOPER_ID" --force ./scripts/postinstall
codesign --entitlements entitlements.plist --timestamp --options=runtime --sign "$DEVELOPER_ID" --force out/myapp.app

echo "pkgbuilding..."
pkgbuild --root ./out/myapp.app --sign "$DEVELOPER_ID" --identifier com.myapp.app --version 1.0 --install-location /Applications/myapp.app --scripts ./scripts ./out/myapp.pkg

echo "productbuilding..."
# productbuild --distribution ./Distribution.xml --package-path ./out/myapp.pkg --resources . ./out/MyAppInstaller.pkg
productbuild --product requirements.plist --distribution ./Distribution.xml --package-path ./out/myapp.pkg --resources . ./out/MyAppInstaller.pkg

productsign --sign "Developer ID Installer: My Company Inc (***)" --force ./out/MyAppInstaller.pkg ./out/MyAppInstallerSigned.pkg

Sidenote: all binaries that are not the main executable, UI, get killed by taskgated, but I figured I will wrap the Worker in its own app Inside Helpers. I just do not see the point in doing that for the token_installer, since it should only be called once ever, during postinstall.

Is there a way to make it run without having to include it in the app bundle itself?

Answered by DTS Engineer in 801603022
Is it not okay to sign the token_installer with the same entitlements as the Worker … ?

Correct.

There are two aspects to this:

  • A provisioning profile is tied to a specific executable via its App ID. TN3125 Inside Code Signing: Provisioning Profiles explains this in detail. Each executable (that needs a profile) should have its own unique App ID, and thus its own profile.

  • For the system to find the executable’s profile, the executable needs to be bundled and the profile embedded in the bundle. Hence the advice in Signing a daemon with a restricted entitlement.


Beyond that, I’m concerned about the execution context of the post-install script that runs your token_installer tool. I’m not an installer expert, so I’m not sure what context that runs in. However, if it runs in a global context then things are going to get weird, because both iCloud and (the data protection) keychain are per-user.

Share and Enjoy

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

Taskgated invalid signature is the error

The trusted execution system does not grant special privileges to executables that are run from installer scripts. Such executables must be signed and notarised, just like any other executable on the system. It looks like that’s not the case, and hence the executable is blocked from running.

This should generate a crash report. Please post an example one here, using the advice in Posting a Crash Report.

Share and Enjoy

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

I am signing the the token installer

codesign --entitlements entitlements.plist --timestamp --options=runtime --sign "$DEVELOPER_ID" --force ./scripts/token_installer
codesign --entitlements entitlements.plist --timestamp --options=runtime --sign "$DEVELOPER_ID" --force ./scripts/postinstall

and notarising the app pkg file

xcrun notarytool submit "./out/MyApp.pkg" --apple-id "account@account.com" --team-id "XXXXX" --password "XXXX" --wait

and stapling the pkg.

xcrun stapler staple "out/MyApp.pkg"

I tried moving the token_installer to Helpers but it did not help (same error). Embedding the worker in its own .app worked using another provisioning profile. But I just need to run the token installer once so it seem like an overkill to create a specific app for just one install script.

This happens when the postinstall script runs on a user machine.

Everything works if I make the user download the companies provision profile onto their system.


Translated Report (Full Report Below)

Incident Identifier: 76F6E5D1-337E-4B44-8228-006A89239424 CrashReporter Key: 7A640EBF-7177-0590-E93F-6DB1D0226437 Hardware Model: Mac15,12 Process: token_installer [3952] Path: /Applications/MyApp.app/Contents/Helpers/token_installer Identifier: token_installer Version: ??? Code Type: ARM-64 (Native) Role: Unspecified Parent Process: Exited process [3934] Coalition: com.apple.package-script-service [1078] Responsible Process: iTerm2 [863]

Date/Time: 2024-08-07 10:03:15.2535 +0000 Launch Time: 2024-08-07 10:03:15.1960 +0000 OS Version: macOS 14.5 (23F79) Release Type: User Report Version: 104

Exception Type: EXC_CRASH (SIGKILL (Code Signature Invalid)) Exception Codes: 0x0000000000000000, 0x0000000000000000 Termination Reason: CODESIGNING 1 Taskgated Invalid Signature

Triggered by Thread: 0

Thread 0 Crashed: 0 0x1032a0b70 _dyld_start + 0

Thread 0 crashed with ARM Thread State (64-bit): x0: 0x0000000000000000 x1: 0x0000000000000000 x2: 0x0000000000000000 x3: 0x0000000000000000 x4: 0x0000000000000000 x5: 0x0000000000000000 x6: 0x0000000000000000 x7: 0x0000000000000000 x8: 0x0000000000000000 x9: 0x0000000000000000 x10: 0x0000000000000000 x11: 0x0000000000000000 x12: 0x0000000000000000 x13: 0x0000000000000000 x14: 0x0000000000000000 x15: 0x0000000000000000 x16: 0x0000000000000000 x17: 0x0000000000000000 x18: 0x0000000000000000 x19: 0x0000000000000000 x20: 0x0000000000000000 x21: 0x0000000000000000 x22: 0x0000000000000000 x23: 0x0000000000000000 x24: 0x0000000000000000 x25: 0x0000000000000000 x26: 0x0000000000000000 x27: 0x0000000000000000 x28: 0x0000000000000000 fp: 0x0000000000000000 lr: 0x0000000000000000 sp: 0x000000016d033800 pc: 0x00000001032a0b70 cpsr: 0x00001000 far: 0x0000000000000000 esr: 0x00000000 Address size fault

Binary Images: 0x10329c000 - 0x103327fff () <37bbc384-0755-31c7-a808-0ed49e44dd8e> ??? 0x102dcc000 - 0x10308ffff () <5e25213b-5aa9-3683-b52e-342159040811> ??? 0x0 - 0xffffffffffffffff ??? (*) <00000000-0000-0000-0000-000000000000> ???

Error Formulating Crash Report: dyld_process_snapshot_get_shared_cache failed

Please post that crash report as an attachment; when you post it as text, it’s really hard to read. See Posting a Crash Report for the instructions.

Is token_installer using any restricted entitlements? See TN3125 Inside Code Signing: Provisioning Profiles for a definition of that.

If you embed token_installer in your app, does the ticket returned by the notary service include its cdhash values? To see the contents of the ticket, see Fetching the Notary Log. To learn how to get the cdhash values for your built code, see TN3126 Inside Code Signing: Hashes.

Oh, and the Explore the System Log section of Resolving Trusted Execution Problems has some hints and what to look for in the system log. Does that turn up anything interesting?

Share and Enjoy

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

Thanks for the response!

That was my first thought, that the token installer was using restricted entitlements but I do not think so. It is using icloud entitlements and keychain access which are allowed by the provisioning profile for the Worker binary which is embedded in the Contents directory of the main app bundle. I thought signing the token_installer with the same entitlements as the worker was okay since it is a helper binary that lives in Helpers or Scripts.

When I embedded the token_installer as a standalone executable in the Helpers folder I got a cdhash for the executable and the bundle was accepted by the notary service.

{
      "path": "MyAppSigned.pkg/MyApp.pkg Contents/Payload/Applications/MyApp.app/Contents/Helpers/token_installer",
      "digestAlgorithm": "SHA-256",
      "cdhash": "313ac4f7c8fc70ee40bd890046f9936c8a82c77b",
      "arch": "arm64"
 },

This is the output from the logstream command after a user installs the package

2024-08-08 10:53:01.191975+0000 0x525f9    Default     0x0                  77345  0    taskgated-helper: [com.apple.ManagedClient:ProvisioningProfiles] Starting taskgated-helper
2024-08-08 10:53:01.192470+0000 0x525f9    Default     0x0                  77345  0    taskgated-helper: (libxpc.dylib) [com.apple.xpc:connection] [0x134606740] activating connection: mach=true listener=true peer=false name=com.apple.taskgated.helper
2024-08-08 10:53:01.192668+0000 0x5264f    Default     0x0                  77345  0    taskgated-helper: (libxpc.dylib) [com.apple.xpc:connection] [0x1352041a0] activating connection: mach=false listener=false peer=true name=com.apple.taskgated.helper.peer[324].0x1352041a0
2024-08-08 10:53:01.192823+0000 0x5264f    Default     0x0                  77345  0    taskgated-helper: (ConfigurationProfiles) [com.apple.ManagedClient:ManagedClient] @@@@@ CP_ProvisioningProfilesAreInstalled CP_ProvisioningProfilesAreInstalledHintFlagFileLocation CHECK_FF
2024-08-08 10:53:01.225334+0000 0x5264f    Error       0x0                  77345  0    taskgated-helper: (ConfigurationProfiles) [com.apple.ManagedClient:ProvisioningProfiles] Disallowing mac_token_installer because no eligible provisioning profiles found
2024-08-08 10:53:01.225459+0000 0x4ba8c    Default     0x0                  324    0    amfid: (libxpc.dylib) [com.apple.xpc:connection] [0x12870f020] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()
2024-08-08 10:53:01.225530+0000 0x5264f    Default     0x0                  77345  0    taskgated-helper: (libxpc.dylib) [com.apple.xpc:connection] [0x1352041a0] invalidated after getting a no-senders notification - client is gone
2024-08-08 10:53:01.225540+0000 0x522a1    Error       0x0                  324    0    amfid: (AppleMobileFileIntegrity) [com.apple.MobileFileIntegrity.framework:default] Failure validating against provisioning profiles: <private>
2024-08-08 10:53:01.225582+0000 0x522a1    Error       0x0                  324    0    amfid: (AppleMobileFileIntegrity) [com.apple.MobileFileIntegrity.framework:default] Restricted entitlements not validated, bailing out. Error: Error Domain=AppleMobileFileIntegrityError Code=-413 "No matching profile found" UserInfo={NSURL=<private>, NSLocalizedDescription=No matching profile found}
2024-08-08 10:53:01.225777+0000 0x522a1    Default     0x0                  324    0    amfid: /private/tmp/PKInstallSandbox.RCQIia/Scripts/com.keystrike.app.t8tip0/mac_token_installer not valid: Error Domain=AppleMobileFileIntegrityError Code=-413 "No matching profile found" UserInfo={NSURL=file:///private/tmp/PKInstallSandbox.RCQIia/Scripts/com.keystrike.app.t8tip0/mac_token_installer, NSLocalizedDescription=No matching profile found}
2024-08-08 10:53:01.225839+0000 0x525ef    Default     0x0                  0      0    kernel: (AppleMobileFileIntegrity) AMFI: code signature validation failed.
2024-08-08 10:53:01.225846+0000 0x525ef    Default     0x0                  0      0    kernel: (AppleMobileFileIntegrity) AMFI: bailing out because of restricted entitlements.

As you can see the most interesting logs are:

No eligible provisioning profiles found

Code signature validation failed

Bailing out because of restricted entitlements.

Do you see the problem?

Is it not okay to sign the token_installer with the same entitlements as the Worker, even though they should be apart of the same application bundle?

Again, Thank you for the help I really appreciate it :)

Structure of the application for more context.

└── Contents
    ├── Helpers
    │   └── token_installer
    ├── Info.plist
    ├── MacOS
    │   ├── Worker.app
    │   │   └── Contents
    │   │       ├── Info.plist
    │   │       ├── MacOS
    │   │       │   └── Worker
    │   │       ├── PkgInfo
    │   │       ├── Resources
    │   │       │   ├── com.worker.plist
    │   │       │   └── icon.icns
    │   │       ├── _CodeSignature
    │   │       │   └── CodeResources
    │   │       └── embedded.provisionprofile
    │   └── UI
    ├── PkgInfo
    ├── Resources
    │   ├── com.ui.plist
    │   ├── com.worker.plist
    │   └── icon.icns
    ├── _CodeSignature
    │   └── CodeResources
    └── embedded.provisionprofile
Is it not okay to sign the token_installer with the same entitlements as the Worker … ?

Correct.

There are two aspects to this:

  • A provisioning profile is tied to a specific executable via its App ID. TN3125 Inside Code Signing: Provisioning Profiles explains this in detail. Each executable (that needs a profile) should have its own unique App ID, and thus its own profile.

  • For the system to find the executable’s profile, the executable needs to be bundled and the profile embedded in the bundle. Hence the advice in Signing a daemon with a restricted entitlement.


Beyond that, I’m concerned about the execution context of the post-install script that runs your token_installer tool. I’m not an installer expert, so I’m not sure what context that runs in. However, if it runs in a global context then things are going to get weird, because both iCloud and (the data protection) keychain are per-user.

Share and Enjoy

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

Postinstall fails to run binary in ./scripts
 
 
Q