Signed and Notarized Unix app cannot be executed

Hello,


I know there is a lot of discussion these days about the notarization process, but reading throughout the threads that are open, I could not find one that suited this exact situation.


The problem that I am encountering is the following: I have an Unix app (terminal application), which has the executable and some libraries that are used by it.

All the binaries (executable and libraries) are signed, using an Apple developer certificate, and successfuly notarized. Of course, they are not stapled, because the notarization process does not permit this for binaries.


However, athough they are notarized, whenever I open the application, I get the following error: "<my_app_name> can't be opened because the identity of the developer cannot be confirmed".

If I right-click the application and click "Open", the application will execute and work as expected.


My questions would be:

  • Is this behaviour expected?
  • If it's not expected, what is it that I should change?
  • For this particular case, should I submit for notarziation both the executable and the libraries? Or is it enough to submit just the executable?


Thank you.

Replies

The problem here is that there is a vast array of reasons why the Gatekeeper check can fail, and they all result in the same user-visible error. In some cases you’ll see info in the system log that offers a hint as to the problem (search for

XprotectService
to see such messages) but it’s hard to interpret that.

The most likely problem here is the connection between your main executable and your libraries. Gatekeeper supports two standard models for this:

  • The main executable is in a bundle, and the libraries are nested within that bundle in

    Contents/Frameworks/
    . This is the approach used by apps and other bundled code.
  • The main executable links to the libraries in a fixed location, typically

    /Library/Frameworks/
    .

Other arrangements can make Gatekeeper grumpy.

So, some questions:

  • Are you seeing this on 10.14.6? What about 10.15 beta?

  • How are you launching your “terminal application”?

  • How is it packaged? And how does it reference these libraries?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you for your reply, @eskimo.


Please find the answers to the questions below.


> Are you seeing this on 10.14.6? What about 10.15 beta?


Yes, this issue is only seen with macOS Catalina (10.15 - all beta versions)


> How are you launching your “terminal application”?


There are three ways by which I tried to run the application:

  1. Double-clicking on the application. This will throw out the error pop-up mentioned in the initial message - "<my_app_name> can't be opened because the identity of the developer cannot be confirmed".
  2. Right click on the application, then select "Open" from the pop-up which will be shown. This will actually open the terminal and run the application, and will actually work as expected
  3. From a terminal window, by using "./diagnose". This will produce a similar result as #1, with the expection that the pop-up shown will have the option to "Move to Trash".


The use for this application in itself is more based on option #3. Our customers will embed this application in their product, and when there is a need to run a diagnostic on the device, will simply run automically this app.


> How is it packaged? And how does it reference these libraries?


It is not packaged in any way. The tool is provided as a zip archive, that contains the command line tool (diagnose), as well as 5 dylibs.


The diagnose tool will explicitly link to one of the 5 dylibs and, then, this dylib will explicitly link to the other 4. The loading structure would look similar to the following:


diagnose (dlopen libapi.dylib, using an absolute path)

|

-- libapi.dylib (dlopen lib1.dylib, lib2.dylib, etc., using an absolute path)

|

-- lib1.dylib

-- lib2.dylib

-- lib3.dylib

-- lib4.dylib


All binaries (diganose + libs) are signed using the same Apple certificate, and then sent to notarization (which is successful), in a zip package that contains all of them.


One other thing to mention, because I don't want to create any confusion regarding to the type of the application: the diagnose is a simple C++ command line app, created and compiled with Xcode 9.x, then signed with Xcode 10, in order to enable runtime hardening. The Xcode 9.x is required for compiling becuase it still offers the option to bundle the 32-bit version of the app, that is required by some of the customers.

The Xcode 9.x is required for compiling becuase it still offers the option to bundle the 32-bit version of the app, that is required by some of the customers.

You have customers that still support 10.6? Wow.

Our customers will embed this application in their product, and when there is a need to run a diagnostic on the device, will simply run automically this app.

OK, that complicates matters. What you’re hitting here is a Gatekeeper check. One fundamental feature of Gatekeeper is that it applies to the thing that the user downloads. If your product is embedded within another product, the Gatekeeper check will be applied to that product, and thus it’s the structure of that product that matters.

For example, let’s say your customers create an installer package that embeds your product. They’ll want to notarise and staple that package before shipping it to their customers. When one of their users installs that package, the Gatekeeper check will be applied to the package as a whole. If that passes, and their package is successfully installed, the user will be able to run your tool without hitting Gatekeeper again.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"