Gatekeeper does not allow a bundle to run before manually running spctl --assess of contained dylib files

Hi,


I am creating a plug-in written in a combination of Objective-C and Swift. As such, the bundle contains the following structure:

/Contents/Frameworks/libswiftCore.dylib (and few other Swift's dylib files)

/Contents/Info.plist

/Contents/MacOS/MainProductBinary

/Contents/Resources/ - contains pdfs, nibs etc.


1. I've codesigned and notarized each *.dylib file individually

2. I've codesigned and notarized the bundle as a whole

3. I've packed the bundle and transfered via web (so it becomes quarantined) to a fresh Catalina virtual machime

4. I've installed the third-party host application for which the our product is a plug-in onto the Catalina virtual machine

5. I've placed the plug-in into a folder where the host application expects it


When I start the host application, Gatekeeper complaines that it cannot check the bundle for malvare.


I manually assess the *.dylib files using a Terminal using the commands bellow:

for filename in MyPlugin.bundle/Contents/Frameworks/*.dylib; do
  spctl --assess --verbose=4 --type install "$filename"
done

After running these commands, Gatekeeper becomes satisfied and allows the plug-in to run when I start the host application.


However, I'm not a supporter of an idea to force users to run these commands before installing the plug-in.


Additional notes:

- Running spctl --assess --type install on the whole bundle before manually assessing the *.dylib files reports "rejected". However, running the same command after manually assessing the *.dylib files reports "accepted".


What should I do to make Gatekeeper satisfied without the need to run these commands?

Answered by MCCZ in 407044022

Thanks for your collaboration. After changing the deployment target to 10.14.4 so Swift libraries not being included in the bundle, the Gatekeeper seems to let the plug-in run and the stapler checking tool reports Accepted. Even that the ticketContents still does not contain the overall bundle entry.


I made no other change to the code nor to the commands to build and notarize the bundle.


However, I finally found how to force the notarization service to recognize the overall bundle. The notarization service started to list the overall bundle as well as the Gatekeeper becomes satisfied (even after lowering back to 10.14 so Swift libraries becomes present again) after I added CFBundlePackageType: BNDL into Info.plist. Strange that the notarization service depends on it as if I understand docs correctly, macOS should default to BNDL if the key is not found or not recognized.


Thanks for your collaboration in triggering this issue.

I have to remind you. In my second reply in this thread, I said:

The last few questions I've seen about notarization problems all turned out to be caused by doing something really crazy


And I suggested:

Look at existing plug-in bundles and notice a structural pattern that all well-written plug-ins share. Copy that structure. I've been using OS X since before day one. All of the reports of notarization problems that I've seen (yes, all of them) involve bundle structures unlike anything that I've seen in 20 years.


Raw bundles and plugins are edge cases. The default Xcode Bundle project includes a proper CFBundlePackageType. I would be extremely surprised to see any functional bundle on a Mac that lacks this key. Maybe, if it is missing, the OS will assume BNDL when it loads. But that doesn't imply that all Apple services will behave that way. This particular issue has actually been known for years, since Apple started using online validation for things like the Mac App Store. The official fix is to set a CFBundlePackageType.


Humans write docs. Humans write web services. Humans write dynamic library loading code. But it is very unlikely that same human did all of that. Many people were involved over decades, with different evaluations of what structures were valid enough to be accepted.


Until this thread, I actually didn't know about that edge case of Notarization without a stapled ticket. I suggest that you do not rely on that.

Hi, thanks for your reply. Just to make few things clear and some follow-up notes.


- Stappling the bundle was of no help. The Gatekeeper still refused to allow the bundle to run.


- It's the first and the only thing I have ever written for MacOS, so I have no previous experience to mine from. As such, I rely mostly on docs, sample codes and forums.


- The linked official fix has a topic/message which is quite far from what I was experiencing. I had Info.plist included and I get no error message, so there was no chance I would ever consider looking into it.


- If the docs are not consistent, non-existant or they use too vague language, there is a high change I would follow the version which is not correct.

- If the implementations of the same requirement are not consistent across different parts of the same product and its related services, its hard to find the cause. Xcode was happy, macOS loader was happy, Gatekeeper was sometimes happy, notarization were false-happy.

- If the docs says the field is optional, has a default value and macOS behaves like that, I expect that all the macOS-related parts and services (I consider the notarization service and the Gatekeeper as a native part of macOS) either follow the same logic or issue clear message if they are more strict. If not, I consider that as a bug, either in docs, in design or in a product.


Either way, thanks for your collaboration. It helped me to focus on the right metric (having the overall bundle included in the logs) and to isolate the cause of the issue.

Gatekeeper does not allow a bundle to run before manually running spctl --assess of contained dylib files
 
 
Q