Codesigned app just hangs

I am able to codesign my app and see it signed successfully. But then when I run it is just hangs, i.e. it does launch and shows in the system tray but no window pops up. I am also able to notarize the app successfully, but it seems code signing did something to cause it to not work the same.

codesign -dvvv WhoStoleMyBeard.app Builds/MacOS/Native/App/WhoStoleMyBeard.app/Contents/MacOS/nwjs Identifier=io.nwjs.nwjs Format=app bundle with Mach-O thin (x86_64) CodeDirectory v=20500 size=440 flags=0x10000(runtime) hashes=3+7 location=embedded Hash type=sha256 size=32 CandidateCDHash sha1=04d39f1aa101d131750387c732d865e4187a8084 CandidateCDHashFull sha1=04d39f1aa101d131750387c732d865e4187a8084 CandidateCDHash sha256=476a47ff9f5fb21f44ddee8292c769d4178e02fd CandidateCDHashFull sha256=476a47ff9f5fb21f44ddee8292c769d4178e02fdbeb14a2893133dc64fd818f1 Hash choices=sha1,sha256 CMSDigest=36b3ddcf11edb24217ebb11c435b4b8a745ddbed0d29ec2b9573edce3298e4a1 CMSDigestType=2 CDHash=476a47ff9f5fb21f44ddee8292c769d4178e02fd Signature size=9055 Authority=Developer ID Application: *** Authority=Developer ID Certification Authority Authority=Apple Root CA Timestamp=Jul 19, 2021 at 4:03:15 PM Info.plist entries=31 TeamIdentifier=*** Runtime Version=10.12.0 Sealed Resources version=2 rules=13 files=2235 Internal requirements count=1 size=172


codesign -v --strict --deep --verbose=2 WhoStoleMyBeard.app WhoStoleMyBeard.app: valid on disk WhoStoleMyBeard.app: satisfies its Designated Requirement

Also the console app shows no errors, and I sign like this for every executable in the app:

codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/libffmpeg.dylib
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/libnode.dylib
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Resources/app_mode_loader.app/Contents/MacOS/app_mode_loader
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/Current/Libraries/WidevineCdm/_platform_specific/mac_x64/widevinecdmadapter.plugin
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/Current/Libraries/WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/nwjs\ Framework
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Helper.app/Contents/MacOS/nwjs\ Helper
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/A/Libraries/WidevineCdm/_platform_specific/mac_x64/widevinecdmadapter.plugin
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/A/Libraries/WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/A/Resources/app_mode_loader.app/Contents/MacOS/app_mode_loader
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/A/nwjs\ Framework
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/A/XPCServices/AlertNotificationService.xpc/Contents/MacOS/AlertNotificationService
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/A/Helpers/crashpad_handler
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/Current/Resources/app_mode_loader.app/Contents/MacOS/app_mode_loader
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Libraries/WidevineCdm/_platform_specific/mac_x64/widevinecdmadapter.plugin
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Libraries/WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/Current/nwjs\ Framework
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/Current/XPCServices/AlertNotificationService.xpc/Contents/MacOS/AlertNotificationService
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Versions/Current/Helpers/crashpad_handler
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/XPCServices/AlertNotificationService.xpc/Contents/MacOS/AlertNotificationService
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/Versions/65.0.3325.146/nwjs\ Framework.framework/Helpers/crashpad_handler
codesign -s "Developer ID Application: Neil Collier" --timestamp -f --options runtime WhoStoleMyBeard.app/Contents/MacOS/nwjs
codesign -s "Developer ID Application: Neil Collier" --timestamp --options runtime -f --entitlements entitlements.plist --force WhoStoleMyBeard.app

First up, you do not need to specify --options runtime when signing libraries. That flag is only necessary for main executables. For more hints and tips on this front, see my Signing a Mac Product For Distribution.

Second, the code signing steps you posted indicate serious code nesting problems. Your code should follow the guidelines in the Nested Code section of Technote 2206 macOS Code Signing In Depth.

However, neither of these is likely to be the cause of your hang. As to what’s going on there, it’s hard to say. As an initial debugging test, try signing the code without enabling the hardened runtime. That’ll either avoid the hang or it won’t:

  • If it does, you know that there’s something in your code that doesn’t agree with the extra security checks enabled by the hardened runtime.

  • If it doesn’t, well, that’d be weird (-:

Share and Enjoy

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

This does indeed allow the signed app to launch.

Cool. This is a great result because it changes the problem from My app has mysterious issues with notarisation. to My app is incompatible with the hardened runtime.

If you’re unfamiliar with the hardened runtime, you can learn more about it here.

I have two suggestions for how to proceed here:

  • It looks like your app is based on third-party tooling. If so, you should escalate this via the tool’s support channel to see if they have any explanation as to why their tooling is incompatible with the hardened runtime.

  • The hardened runtime enables a package of additional security features. However, you can selectively disable these using the various hardened runtime exception entitlements (see the doc I referenced above). You could run through each of those entitlements to see if any of them ‘fix’ your app. If so, that’d give you a clue as to where to look in your code to find the hardened runtime incompatibility.

IMPORTANT This second suggestion is, again, a diagnostic test, not a fix. Once you understand which specific security feature your app is having problems with, you can then update your code to resolve that incompatibility. You should try to avoid shipping a product with any hardened runtime exception entitlements enabled because that undermines the whole point of the hardened runtime, namely to raise the security bar on macOS.

Share and Enjoy

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

It would help if you replied using a reply rather than the comments. That’d make it easier to read your text.

Originally you said "you do not need to specify --options runtime when signing libraries. That flag is only necessary for main executables".

That’s correct.

But when I follow those instruction, 6 of the tools say they need the hardened runtime enable by notarization service

A command-line tool is a main executable. I’m using the terms from Signing a Mac Product For Distribution here, which says:

Is it a main executable? (apps, app extensions, command-line tools)

If you’re unsure, use the file command and look for executable in the result:

% file Test685263.app/Contents/MacOS/Test685263 
…
… Mach-O 64-bit executable x86_64
… Mach-O 64-bit executable arm64
% file Test685263.app/Contents/Frameworks/libFFF.dylib 
…
… Mach-O 64-bit dynamically linked shared library x86_64
… Mach-O 64-bit dynamically linked shared library arm64

so which is it...hardened or not hardened?

I think this is simply a case of you not understanding my terminology here [1], and I hope that the above has clarified that.

Also the doc you mention above says “You add entitlements only to executables. Shared libraries, frameworks, and in-process plug-ins inherit the entitlements of their host executable.”

That’s correct.

Clearly this is not the case, since I hardened the main executable but it complains the child frameworks are not hardened.

OK, you’re definitely confused here. The hardened runtime is enabled by a code signing flag. This is different from entitlements, which is a separate property of the code signature.

Having said that, both the hardened runtime flag and the entitlements are only effective when applied to main executables.

Note Enabling the hardened runtime flag on library code is always benign. Adding entitlements to library code can prevent the code from loading.

I am not personally in control of the tooling here

OK. In that case you should escalate this with your tooling’s vendor. Their tooling should be able to produce products that are compatible with the hardened runtime.

Share and Enjoy

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

[1] Just to be sure, I created a small test app with a shared library and notarised that:

% codesign -d -vvv Test685263.app/Contents/MacOS/Test685263 2>&1 | grep flags 
CodeDirectory v=20500 size=531 flags=0x10000(runtime) hashes=9+3 location=embedded
% codesign -d -vvv Test685263.app/Contents/Frameworks/libFFF.dylib 2>&1 | grep flags
CodeDirectory v=20400 size=330 flags=0x0(none) hashes=5+2 location=embedded
% curl "https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma125/…
{
  …
  "ticketContents": [
    …
    {
      "path": "Test685263.zip/Test685263.app/Contents/Frameworks/libFFF.dylib",
      "digestAlgorithm": "SHA-256",
      "cdhash": "af3f614e0c4813a86791437f4f4246a757a0505b",
      "arch": "x86_64"
    },
    …
  ],
  "issues": null
}

As you can see, the app has the hardened runtime flag set and the library does not, and yet it still notarises just fine.

if the entitlements file does not apply the exception how do I do as you suggested in the previous comment

There are two things here:

  • Code signing flags, including the hardened runtime flag

  • Entitlements, including the hardened runtime exception entitlements

To sign an executable with the hardened runtime enabled, pass in -o runtime:

% codesign -s "Developer ID Application" -f --timestamp -o runtime Test685263.app
Test685263.app: replacing existing signature

To opt out of a specific hardened runtime security feature using a hardened runtime exception entitlement, create a property list file with the entitlements and pass it in via --entitlements:

% cat Test685263.entitlements 
<?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.cs.allow-jit</key>
    <true/>
</dict>
</plist>
% codesign -s "Developer ID Application" -f --timestamp -o runtime --entitlements Test685263.entitlements Test685263.app 

And, to reiterate, this is only relevant for main executables (apps, app extensions, command-line tools, and so on). A library (framework, shared library, bundle, and so on) does not need either the hardened runtime flag or entitlements.

this should allow me to at least understand what part is at fault to tell the 3rd party vendor

If your vendor needs help with this please encourage them to either chime in here (for informal support) or open a DTS tech support incident (so that I can help them officially).

Share and Enjoy

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

Codesigned app just hangs
 
 
Q