Notarization error for "Growl.framework" and "libchilkatCocoa.a"

Hi,

I am a software developer at https://www.continuum.net/ now https://www.connectwise.com/. We have a macOS package that was built 7-8 years back by some other organization. Now when I try to notarize this app by signing and recompile it, I few errors for 3rd party package "Growl.framework" and for a static library "libchilkatCocoa.a".


1. Error "The binary uses an SDK older than the 10.9 SDK" for "Growl.framework".

2. "The binary is not signed for "libchilkatCocoa.a".


https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma113/v4/3a/62/b0/3a62b0e5-99d6-e0f4-a6ef-eaadf887f95c/developer_log.json?accessKey=1574270418_5198680920624751432_1EPanIVvmOtLsYnJzcGlsYn0kdh9GhFP0LtpAKvAqjp8kcRNPKH%2BKOniWK9r7kM79ZVH1muQm2hyeWbfJrj7hAT76CBB6i63Ha7%2BCLIDLOibeWnKO8IGdvYvoEatkFiTKHVlre0E9qTGKJrUpycPDfx8vSxHg3wJCZCkVmGaymU%3D


Could you please help me understand how I can resolve these issues or if there is any workaround for this as I cannot recompile these as they are 3rd party framework.



Thanks in advance!!!

Accepted Reply

OK, let’s tackle your problems in order.

SDK Version

There’s really not much you can do here. Notarisation requires modern code signing and, in order to be guaranteed that it has modern code signing, it requires that your components link with the 10.9 SDK or later. There’s only two supported ways to fix this:

  • Remove your dependency on the Growl framework.

  • Get a version of that framework that’s built against a modern SDK.

Static Libraries

The vast majority of folks who end up shipping static libraries (

.a
files) to end users do so by mistake [1]. Thus, in most cases the correct answer here is to remove the static library from your shipping product.

As to the actual symptoms you’re seeing, I looked into the situation with static libraries just yesterday as part of a DTS incident and thus I can explain the observed behaviour:

  • Static libraries come in two flavours:

    • Traditional static libraries are in

      ar
      format (see the
      ar
      man page, making sure to look in both sections 1 and 5).
    • Universal static libraries are Mach-O universal containers (see

      <mach-o/fat.h>
      ) where each slice is in
      ar
      format.

    Both of these have the

    .a
    extension, so it’s easy to get confused. It’s even possible to have a universal static library that contains a single architecture!

    You can tell these apart using

    file
    :
    $ file libXXX.a 
    … current ar archive random library
    $ file libUniversalXXX.a 
    … Mach-O universal binary with 1 architecture: [x86_64:current ar archive random library]
    … (for architecture x86_64): current ar archive random library

    .

  • For universal libraries, the presence of the Mach-O universal container convinces the notarisation system that the file must be code signed. It’s not clear to me whether’s that good or bad choice, and I’ve escalated that analysis to Apple’s R&D engineering (r. 57321912).

  • When you try to sign such a static library, things go a bit wonky. For a normal Mach-O, the code signature is stored in the Mach-O itself. For a normal universal Mach-O, the code signature is stored separately in each slice. However, there’s no place to store a code signature in a static library, and so a static library ends up being signed as data, not code. That results in the code signature being stored in extended attributes:

    $ codesign -s "Developer ID App" --timestamp libUniversalXXX.a 
    $ ls -l@ libUniversalXXX.a 
    -rw-r--r--@ 1 quinn  staff  2720 19 Nov 15:14 libUniversalXXX.a
        com.apple.cs.CodeDirectory   130 
        com.apple.cs.CodeRequirements    168 
        com.apple.cs.CodeRequirements-1  166 
        com.apple.cs.CodeSignature  9003

    In general we recommend against storing code signatures in extended attributes. In fact, in most cases it’s a sign that you have a nested code problem.

  • One gotcha with storing code signatures in extended attributes is that it’s not uncommon for extended attributes to get dropped. This is what’s happening in your case. The problem is that you’re using

    zip
    and
    unzip
    , which are cross-platform tools that don’t understand extended attributes. The extended attributes don’t survive this round trip, and thus the code signature ‘disappears’.

    When creating and expanding zip archives for notarisation purposes, always use

    ditto
    . For an example, see Customizing the Notarization Workflow.

So, to summarise:

  • You will need a new version of Growl, or simply remove that dependency.

  • Stop including

    libchilkatCocoa.a
    in your shipping product. That static library is meant as an input to the linker, not to be distributed.
  • If you come across a static library that is meant to be distributed, the notarisation story is nuanced and we should discuss the details.

Share and Enjoy

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

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

[1] There are some third-party development environments that include static libraries as part of their runtime, but that doesn’t seem to be what’s happening here.

Replies

You can’t resolve it. It is a 3rd party framework. And it appears to have been build improperly. The developer didn’t seem to know how to use a static library. You can just get rid of the libchilkatcocoa.a file. Go ahead and get rid of Growl too. You will get some code-level errors, but they can be easily fixed by changing them to use local notifications.

Thanks for the reply!!!


Seems like I will have to go without Growl.framework but I am not able to understand why the static library "libchilkatCocoa.a" gave error "The binary is not signed." even though it was signed.


apples-Mac-mini:a engguser$ codesign --verbose=9 --deep --options=runtime --timestamp -f -s 'Developer ID Application: ***' libchilkatCocoa.a
libchilkatCocoa.a: replacing existing signature
libchilkatCocoa.a: signed generic [libchilkatCocoa]
apples-Mac-mini:a engguser$ codesign --verbose=9 --deep --verify libchilkatCocoa.a
libchilkatCocoa.a: valid on disk
libchilkatCocoa.a: satisfies its Designated Requirement


BTW, I have observed that all the non-executable files including static files lose their signature when zipped and unzipped. Is this expected behavior? any comments on this?


apples-Mac-mini:lib engguser$ zip libchilkatCocoa.zip libchilkatCocoa.a
  adding: libchilkatCocoa.a (deflated 69%)
apples-Mac-mini:lib engguser$ rm libchilkatCocoa.a
apples-Mac-mini:lib engguser$ unzip libchilkatCocoa.zip libchilkatCocoa.a
Archive:  libchilkatCocoa.zip
  inflating: libchilkatCocoa.a
apples-Mac-mini:lib engguser$ codesign --verbose=9 --deep --verify libchilkatCocoa.a
libchilkatCocoa.a: code object is not signed at all
apples-Mac-mini:lib engguser$

The Growl framework was an ancient library to display notifications. It should be trivial to change any usages to the current local notification framework. It is very easy.


A .a file is a static archive file. It is a library that is meant to be linked into an exectuable. Then you would sign the executable. There is no need to ever distribute a static archive. It would be completely useless. You may need to link with that file, but you should not be distributing it. Just delete it from Xcode's list of resources. And since there is an archive in there, maybe review that list of resources for other files or data that should not be there.


Zipping does not delete signatures. Make sure to use the Finder's context menu to "compress" apps. That is what most users are going to use anyway. This will properly encode any resource forks or extended attributes.

OK, let’s tackle your problems in order.

SDK Version

There’s really not much you can do here. Notarisation requires modern code signing and, in order to be guaranteed that it has modern code signing, it requires that your components link with the 10.9 SDK or later. There’s only two supported ways to fix this:

  • Remove your dependency on the Growl framework.

  • Get a version of that framework that’s built against a modern SDK.

Static Libraries

The vast majority of folks who end up shipping static libraries (

.a
files) to end users do so by mistake [1]. Thus, in most cases the correct answer here is to remove the static library from your shipping product.

As to the actual symptoms you’re seeing, I looked into the situation with static libraries just yesterday as part of a DTS incident and thus I can explain the observed behaviour:

  • Static libraries come in two flavours:

    • Traditional static libraries are in

      ar
      format (see the
      ar
      man page, making sure to look in both sections 1 and 5).
    • Universal static libraries are Mach-O universal containers (see

      <mach-o/fat.h>
      ) where each slice is in
      ar
      format.

    Both of these have the

    .a
    extension, so it’s easy to get confused. It’s even possible to have a universal static library that contains a single architecture!

    You can tell these apart using

    file
    :
    $ file libXXX.a 
    … current ar archive random library
    $ file libUniversalXXX.a 
    … Mach-O universal binary with 1 architecture: [x86_64:current ar archive random library]
    … (for architecture x86_64): current ar archive random library

    .

  • For universal libraries, the presence of the Mach-O universal container convinces the notarisation system that the file must be code signed. It’s not clear to me whether’s that good or bad choice, and I’ve escalated that analysis to Apple’s R&D engineering (r. 57321912).

  • When you try to sign such a static library, things go a bit wonky. For a normal Mach-O, the code signature is stored in the Mach-O itself. For a normal universal Mach-O, the code signature is stored separately in each slice. However, there’s no place to store a code signature in a static library, and so a static library ends up being signed as data, not code. That results in the code signature being stored in extended attributes:

    $ codesign -s "Developer ID App" --timestamp libUniversalXXX.a 
    $ ls -l@ libUniversalXXX.a 
    -rw-r--r--@ 1 quinn  staff  2720 19 Nov 15:14 libUniversalXXX.a
        com.apple.cs.CodeDirectory   130 
        com.apple.cs.CodeRequirements    168 
        com.apple.cs.CodeRequirements-1  166 
        com.apple.cs.CodeSignature  9003

    In general we recommend against storing code signatures in extended attributes. In fact, in most cases it’s a sign that you have a nested code problem.

  • One gotcha with storing code signatures in extended attributes is that it’s not uncommon for extended attributes to get dropped. This is what’s happening in your case. The problem is that you’re using

    zip
    and
    unzip
    , which are cross-platform tools that don’t understand extended attributes. The extended attributes don’t survive this round trip, and thus the code signature ‘disappears’.

    When creating and expanding zip archives for notarisation purposes, always use

    ditto
    . For an example, see Customizing the Notarization Workflow.

So, to summarise:

  • You will need a new version of Growl, or simply remove that dependency.

  • Stop including

    libchilkatCocoa.a
    in your shipping product. That static library is meant as an input to the linker, not to be distributed.
  • If you come across a static library that is meant to be distributed, the notarisation story is nuanced and we should discuss the details.

Share and Enjoy

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

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

[1] There are some third-party development environments that include static libraries as part of their runtime, but that doesn’t seem to be what’s happening here.