Notarizing a loadable bundle

Hi


I'm trying to notarize a plug-in for Adobe Illustrator (project type: Mach-O Bundle).

I have signed it with a Developer Id certificate and have enabled hardened runtime. The bundle contains 2 binaries: the main binary and a helper tool. Both binaries are reported signed by codesign -d -vv, as well as the bundle itself is.

After a few attempts I finally managed to get "Package Approved" from the notary service, but the approval only contains a ticket for the helper tool, but not for the main bundle binary.


Some of our products don't contain a helper tool. Trying to notarize such a bundle, I always get an error saying "Package has no signed executables or bundles. No tickets can be generated".


Is this normal behavior, or am I doing something wrong? Non-notarized bundles are no longer loaded by the host application on macOS 10.15 beta.

Replies

I'm seeing the same behavior for plug-ins used by our application (not related to Adobe but similar idea). Our plugins never contain helper tools, so we only see the error about "Package has no signed executables or bundles. No tickets can be generated" when trying to notarize. And then the bundles aren't loaded when running on Catalina.


Our application (which is itself notarized) that loads our plugins has the following entitlements set, yet they don't seem to avoid the need to notarize our plugins:

com.apple.security.cs.allow-jit
com.apple.security.cs.allow-unsigned-executable-memory
com.apple.security.cs.allow-dyld-environment-variables
com.apple.security.cs.disable-library-validation
com.apple.security.cs.disable-executable-page-protection
com.apple.security.get-task-allow
com.apple.security.device.audio-input
com.apple.security.device.camera
com.apple.security.automation.apple-events

It's not clear to me whether setting these entitlements should avoid the need for our plugins to be notarized or not. They are code signed but that doesn't seem to be sufficient.

Thanks for confirming!

At least I'm not the only one experiencing this.


It would be good to hear a comment from Apple — perhaps there's a (hopefully temporary) problem with the notary service?

I was finally able to successfully notarize my plugin bundle in such a way that the main application can load the plugin. This is not pretty.


Our plugins are bundles with the .xop extension. I renamed the bundle to have the .app extension, and then created a .dmg container to hold the bundle. I then uploaded the .dmg to the notary service. The notary service accepted and notarized the .dmg. When I look at the log for the notarization process, there are two entries in the "ticketContents" array, one for the outer .dmg file itself and one for the .app file. The actual executable in the bundle, located in Contents/MacOS, is not included in the ticketContents list. However, a few minutes after the notarization succeeded, I was able to run my application on a separate machine and the bundle, still with the original .xop extension, was successfully loaded by my application.


I have not yet tested whether stapling a ticket to my .xop bundle works, or if I can staple the ticket to the temporarily named .app bundle and then rename give it the .xop extension.


It is also not clear why I need to go to the trouble to notarize the plugin in the first place since my main application includes the com.apple.security.cs.disable-library-validation entitlement.


I have also not tested whether a plugin signed/notarized by a different developer certificate than the main application will load.


For the record, I am doing the code signing and notarization on Mojave, and testing the application on 10.15 beta 3. Also, the .xop bundle itself does NOT use hardened runtime. Based on the documentation for hardened runtime, it is the application that controls the hardened runtime entitlements, not the plugin. But I don't know if that documentation is actually correct.

Just as an experiment, I created a small test bundle from the macOS > Bundle template and tried notarising that [1]. It worked as expected, in that notarisation was successful and the ticket contains a

cdhash
that matches the bundle’s code signature.

You should check that your bundle has the

CFBundleExecutable
property set correctly in its
Info.plist
. I’ve seen folks run into problems because of that.

Beyond that, my recommendation is that you do what I did, that is, create a new test bundle to see if it works. If it does, you have a known working case and you can diff from there. If it doesn’t, we can look into what you and I did differently.

Share and Enjoy

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

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

[1] I had to add a dummy

.c
file so that the bundle actually contained code.

I suspect that, for notarization to succeed, the bundle must have the extension ".app" or ".bundle".


That should not be required because there has never been any requirement that an executable bundle have a particular extension.


I hope Apple will fix this because, if not, it will create problems for us and for thousands of our users at universities and research labs all over the world.


UPDATE: Our testing indicates that notarization fails if the CFBundlePackageType is not BNDL *and* the package extension is not .app. It succeeds if CFBundlePackageType is BNDL *or* if the package extension is .app.


We use CFBundlePackageType=IXOP because it distinguishes our particular type of plug-in AND because it allows us to associate a custom icon with plug-ins of this type.

I just checked and the bundle extension seems to have no effect.

For me, it fails with either "bundle" or "aip" for preexisting bundles, and it succeeds with a fresh new test bundle regardless of the extension.


So the service seems to be extension-neutral. I'd count this as good news.

I tried the .dmg approach but the success is at best partial. It reports "Package Approved" but only returns a ticket for the dmg itself. I suspect the service silently ignores the bundle binary in this case.


Stapling the dmg works, but its contents remain unchanged. This ticket cannot be used to staple individual bundles.

Furthermore, deploying a plug-in by copying it from that dmg (provided it has the qarantine attribute set) still does not allow the host app to load it.


BTW, you might want to check that your notarized bundle works on another machine if it was downloaded from the Internet. If there's no quarantine flag on it, the verification step is omitted.

OK, thanks. I also tried with a new empty bundle project and I was able to successfully notarize it.


But still I need to make sure our old projects continue to work.

I've checked and the CFBundleExecutable property is set correctly. Any hints on what plist properties to check besides CFBundleExecutable? I was hoping to avoid rebuilding all products at this stage. The bundles were built with 10.12 SDK and they target macOS 10.10+.

The projects were originally based on a templafe from Adobe so there might be some legacy properties (LSRequiresCarbon, CFBundlePackageType, CFBundleSignature etc.)


Unfortunately, the service does not include any error messages explaining why the bundle was ignored. Only "no signed executables or bundles".

I reviewed the bundle Info.plist and made some changes:

- set CFBundlePackageType to BNDL; for historic reasons it was set to ARPI (I think it was Adobe's requirement for plug-ins at some point)

- deleted the CFBundleSignature key

- deleted the LSRequiresCarbon key


After that, the bundle was notarized successfully, and loaded by the host application.

That settles it, I guess. Still, a verbose error message explaining why the bundle was not processed would be of great help.

Our .xop bundles set CFBundlePackageType to IXOP in the Info.plist. I tried changing IXOP to BNDL for one of the .xop bundles. After re-codesigning and resubmitting to the notary service, I see that both the outer .dmg and now the .xop bundle is listed in ticketContents.


The legacy documentation at https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-111321 states "For loadable bundles, you can also choose a type code that is more specific than

BNDL
if you want.". The newer documentation at https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundlepackagetype?language=objc leaves it ambiguous as to whether it is allowed to use a custom type code for a bundle.

BTW, you might want to check that your notarized bundle works on another machine if it was downloaded from the Internet. If there's no quarantine flag on it, the verification step is omitted.


Yes, the machine on which I tested is running Catalina while the notarization was done on Mojave. On the Catalina machine, I tested for notarization success both by running spctl and running the application which loads the bundle. Prior to notarization, the .xop failed to load. After notarizing (again, on a different machine) and then waiting a few minutes, I was now able to run the application with the .xop loading on the Catalina machine. I didn't change the .xop that's loading at all, so the OS must have looked up the notarization ticket online, since it wasn't attached to the .xop bundle on that machine.

Interesting. That didn't work for me. But I finally managed to make the bundle (with the original .aip extension) pass notarization by fixing its Info.plist

DmitryO wrote:

Still, a verbose error message explaining why the bundle was not processed would be of great help.

Agreed. Please do file a bug report requesting that. Make sure to include the UUID of the submission that failed and the submission that succeeded.

Please post your bug number, just for the record.

RGB255 wrote:

Our

.xop
bundles set
CFBundlePackageType
to
IXOP
in the
Info.plist
. I tried changing
IXOP
to
BNDL
for one of the
.
xop bundles. After re-codesigning and resubmitting to the notary service, I see that both the outer
.
dmg and now the
.xop
bundle is listed in
ticketContents
.

OK, that sounds like a clear explanation as to what’s failing. If you’re OK with changing the

CFBundlePackageType
property in general, that’s the best way forward. If there are problems with doing that in general, the only option I can see is to file a bug against the notarisation service.

Share and Enjoy

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

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

Thanks Quinn. I will file a bug report about the failure to notarize a bundle with a custom CFBundlePackageType property.


But can you tell me this--given that the application has the entitlements I gave in my first post in this thread (specifically com.apple.security.cs.disable-executable-page-protection), should notarization of the bundle (.xop) be required in the first place? This seems like a bug to me, but since the documentation for that entitlement is so sparse I'm not sure if I'm misunderstanding its purpose or not.


For what it's worth, I have used codesign to view the entitlements of the application while it is running (you gave instructions to do this in another thread) and they are as I expect them to be. And I am able to do things with the application such as access the camera and debug the application.

FWIW, I filed FB6716476 about the failure to notarize a loadable bundle with CFBundlePackageType = IXOP.