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.

The only thing you need to notarize is the top-level installer package. If you are doing something funky like a plug it, then it is a little more complicated. Look for any number of posts by eskimo explaining how to do it.

I've tried notarizing only the outer package but I failed. As I noted in the linked thread, everything started working when I removed all dylib from the plug-in. As official docs were of no help, I've searched web and I've found lots of thread stating issues if dylib files are present but missing any answer. Then I found this thread stating that if they notarized dylib files separatedly, it helped. So I've tried that and really, it made a progress.


It's strange that the assessment fails unless I perform assessment on inside files first. I would expect that manually performing assessments on inside files would not change the outcome of the bundle-wide assessment as it should be either ok or not. The behaviour I experience is quite weird to me as it reports the exactly same binaries both as rejected and as accepted.

In step 3, how did you package up the you’re plug-in?

Share and Enjoy

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

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

1. In production, I tar czf the whole directory which contains the bundle (the parent directory contains additional files like How to PDF etc.).

2. While investigating, I was also trying the exactly same zip file sent for notarization by the xcrun altool --notarize-app command (the zip file was created calling ditto -c -k --keepParent --rsrc)

I think that since notarization requires proper signing, the author of that post assumed there was something else going on. Proper signing is all that is necessary.


That being said, it is difficult to speculate about what is going wrong. The last few questions I've seen about notarization problems all turned out to be caused by doing something really crazy to get those dylibs inside the bundle. I'm not sure what people are doing. 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.


Plugins are more of an outlier since they are based more on what the containing app expects to see. But surely, for every app worth having plug-ins, there have got to be some examples of properly notarized plug-ins. Find them and copy their structure. If you still have problems, then at least you will have something to reference.

I've included the plug-in's file structure at the top of the question above. I've skipped just the files created by codesign and spctl.

OK. One factoid about both of these container formats is that they don’t support stapling. Honestly, I’m not yet sure if that’s relevant.

Earlier you wrote:

I've tried notarizing only the outer package but I failed.

To be clear, notarising the outermost container (which in this case is your plug-in’s bundle) is the correct option here. Notarising subcomponents is a bad idea in general and I’ve seen it trigger weird problems in situations similar to this.

If you do notarise just the outermost container, what does the notarisation log look like? I’m specifically interested in:

  • If there are any warnings in the

    issues
    property
  • The list of all the paths under the

    ticketContents
    property

Also, what does the your plug-in layout look like? If do you do this:

% find MyPlugin.bundle

what does it print? I realise that may be a long list, so feel free to condense stuff that’s all going to be treated the same (for example, if

Contents/Resources/
contains 27 PDFs, you can elide 26 of them).

Finally, one more question on a completely different tack. Does the host app guaranteed to load your plug-in in a separate process? Or does it load it within the host app’s process?

Also, what’s the deployment target for your plug-in?

This matters because, if the host app loads your plug-in into its own process and you support systems prior to 10.14.4, it’s not safe to use Swift in your plug-in. In 10.14.4 we bundled the Swift runtime in the OS, so you don’t need all of those Swift libraries in the first place. On earlier systems the Swift runtime gets loaded from your plug-in, but that’s problematic because any given process can only have one copy of the Swift runtime and you can’t guarantee that when building an in-process plug-in (the app might have its own Swift runtime, or there may be other in-process plug-ins with their own Swift runtime).

Share and Enjoy

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

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

After sending to a notarization service.

% find MyPlugin.bundle
MyPlugin.bundle
MyPlugin.bundle/Contents
MyPlugin.bundle/Contents/_CodeSignature
MyPlugin.bundle/Contents/_CodeSignature/CodeResources
MyPlugin.bundle/Contents/MacOS
MyPlugin.bundle/Contents/MacOS/MyPlugin
MyPlugin.bundle/Contents/Resources
MyPlugin.bundle/Contents/Resources/[pdf, nib, pem files]
MyPlugin.bundle/Contents/Resources/MyPlugin-Prefix.pch
MyPlugin.bundle/Contents/Frameworks
MyPlugin.bundle/Contents/Frameworks/libswiftObjectiveC.dylib
MyPlugin.bundle/Contents/Frameworks/libswiftCore.dylib
MyPlugin.bundle/Contents/Frameworks/libswiftCoreGraphics.dylib
MyPlugin.bundle/Contents/Frameworks/libswiftDispatch.dylib
MyPlugin.bundle/Contents/Frameworks/libswiftCoreFoundation.dylib
MyPlugin.bundle/Contents/Frameworks/libswiftDarwin.dylib
MyPlugin.bundle/Contents/Frameworks/libswiftIOKit.dylib
MyPlugin.bundle/Contents/Frameworks/libswiftFoundation.dylib
MyPlugin.bundle/Contents/Info.plist

Notarization log (I've just stripped jobId, uploadDate, sha256 and cdhash, renamed actual zip and bundle names to a dummy names):

{
  "logFormatVersion": 1,
  "status": "Accepted",
  "statusSummary": "Ready for distribution",
  "statusCode": 0,
  "archiveFilename": "MyPlugin.zip",
  "ticketContents": [
    {
      "path": "MyPlugin.zip/MyPlugin.bundle/Contents/MacOS/MyPlugin",
      "digestAlgorithm": "SHA-256",
      "arch": "x86_64"
    },
    {
      "path": "MyPlugin.zip/MyPlugin.bundle/Contents/Frameworks/libswiftObjectiveC.dylib",
      "digestAlgorithm": "SHA-256",
      "arch": "x86_64"
    },
    {
      "path": "MyPlugin.zip/MyPlugin.bundle/Contents/Frameworks/libswiftCore.dylib",
      "digestAlgorithm": "SHA-256",
      "arch": "x86_64"
    },
    {
      "path": "MyPlugin.zip/MyPlugin.bundle/Contents/Frameworks/libswiftCoreGraphics.dylib",
      "digestAlgorithm": "SHA-256",
      "arch": "x86_64"
    },
    {
      "path": "MyPlugin.zip/MyPlugin.bundle/Contents/Frameworks/libswiftDispatch.dylib",
      "digestAlgorithm": "SHA-256",
      "arch": "x86_64"
    },
    {
      "path": "MyPlugin.zip/MyPlugin.bundle/Contents/Frameworks/libswiftCoreFoundation.dylib",
      "digestAlgorithm": "SHA-256",
      "arch": "x86_64"
    },
    {
      "path": "MyPlugin.zip/MyPlugin.bundle/Contents/Frameworks/libswiftDarwin.dylib",
      "digestAlgorithm": "SHA-256",
      "arch": "x86_64"
    },
    {
      "path": "MyPlugin.zip/MyPlugin.bundle/Contents/Frameworks/libswiftIOKit.dylib",
      "digestAlgorithm": "SHA-256",
      "arch": "x86_64"
    },
    {
      "path": "MyPlugin.zip/MyPlugin.bundle/Contents/Frameworks/libswiftFoundation.dylib",
      "digestAlgorithm": "SHA-256",
      "arch": "x86_64"
    }
  ],
  "issues": null
}

I am not sure but I think the plug-in is loaded within the host app's process.

Deployment target is 10.14.

Swift language version is Swift 5.

I'm aware of the possible compatibility issues if different Swift runtimes are present in a process. The host app is pure Objective-C and our plug-in is the only plug-in using Swift. We re in a process of moving the Swift part to Objective-C. The replacement is not ready yet so we need to get the Swift version working in Catalina for a while.

I've then copied the zip file sent to the notarization service to the 10.15 virtual machine, unzipped and run spctl --assess:


% spctl --assess --type install -vvvv MyPlugin.bundle
MyPlugin.bundle: rejected
source=Unnotarized Developer ID
origin=Developer ID Application: OurTeamName (OutTeamId)

% spctl --assess --type exec -vvvv MyPlugin.bundle
MyPlugin.bundle: rejected (the code is valid but does not seem to be an app)
origin=Developer ID Application: OurTeamName (OutTeamId)

% spctl --assess -vvvv MyPlugin.bundle
MyPlugin.bundle: rejected (the code is valid but does not seem to be an app)
origin=Developer ID Application: OurTeamName (OutTeamId)

Thanks for all the info. To start, a simple FYI: You should not be shipping the following to users:

MyPlugin.bundle/Contents/Resources/MyPlugin-Prefix.pch

It’s essentially a source file. This isn’t a problem for notarisation, it’s just a bit weird.

As to what’s going wrong with your plug-in, I have a theory. I created and notarised a test bundle here in my office. Consider its notarisation log:

{
  …
  "ticketContents": [
    {
      "path": "Test129024.dmg",
      "digestAlgorithm": "SHA-256",
      "cdhash": "359cbf51ee16eddc4e61430b2b8757abae42747b"
    },
    {
      "path": "Test129024.dmg/Test129024.bundle",
      "digestAlgorithm": "SHA-256",
      "cdhash": "7a5ee947ed19761162d342c4a511126cc55c8459",
      "arch": "x86_64"
    },
    {
      "path": "Test129024.dmg/Test129024.bundle/Contents/MacOS/Test129024",
      "digestAlgorithm": "SHA-256",
      "cdhash": "7a5ee947ed19761162d342c4a511126cc55c8459",
      "arch": "x86_64"
    }
  ],
  "issues": null
}

Note how there’s an entry for the bundle and an entry for the executable within the bundle. In your case you only have an entry for the executable, you don’t have an entry for the bundle as a whole. Something about your submission is causing the notary service to not recognise your bundle as a bundle.

I’ve seen problems like this before where folks accidentally built their zip archive without the parent directory of their app. However, that doesn’t look like the case here.

To test this theory, I have a new diagnostic test for you: Try submitting a disk image. To get you started, here’s the commands I used to create a disk image from my bundle:

% mkdir Test129024
% mv Test129024.bundle Test129024
% hdiutil create -srcFolder Test129024 Test129024.dmg
% codesign -s "Developer ID App" --timestamp Test129024.dmg

One of two things will happen here:

  • The disk image’s ticket will have an entry for the overall bundle. In that case we know there’s something wonky about your zip archive packaging.

  • Or it won’t, in which case we need to look at how your bundle is structured.

Share and Enjoy

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

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

Thanks for the pch recommendation. I'll remove it from the bundle after we fix the notarization.


Neither the disk image's ticket has an entry for the overall bundle - it contains every entry present in the zip's ticket (the executable file and the dylib files) plus an entry for the dmg file, but not for the overall bundle. It also has issues: null.


The bundle file structure is in an above reply. If I understand Bundle Structures correctly, our bundle is a Loadable Bundle and all the paths are standard and all the required files of Loadable Bundle are there.


Here's the dmg content:

% find /Volumes/1
/Volumes/1
/Volumes/1/MyPlugin.bundle
/Volumes/1/MyPlugin.bundle/Contents
/Volumes/1/MyPlugin.bundle/Contents/_CodeSignature
/Volumes/1/MyPlugin.bundle/Contents/_CodeSignature/CodeResources
/Volumes/1/MyPlugin.bundle/Contents/MacOS
/Volumes/1/MyPlugin.bundle/Contents/MacOS/MyPlugin
/Volumes/1/MyPlugin.bundle/Contents/Resources
/Volumes/1/MyPlugin.bundle/Contents/Resources/[pdf, nib, pem files]
/Volumes/1/MyPlugin.bundle/Contents/Resources/MyPlugin-Prefix.pch
/Volumes/1/MyPlugin.bundle/Contents/Frameworks
/Volumes/1/MyPlugin.bundle/Contents/Frameworks/libswiftObjectiveC.dylib
/Volumes/1/MyPlugin.bundle/Contents/Frameworks/libswiftCore.dylib
/Volumes/1/MyPlugin.bundle/Contents/Frameworks/libswiftCoreGraphics.dylib
/Volumes/1/MyPlugin.bundle/Contents/Frameworks/libswiftDispatch.dylib
/Volumes/1/MyPlugin.bundle/Contents/Frameworks/libswiftCoreFoundation.dylib
/Volumes/1/MyPlugin.bundle/Contents/Frameworks/libswiftDarwin.dylib
/Volumes/1/MyPlugin.bundle/Contents/Frameworks/libswiftIOKit.dylib
/Volumes/1/MyPlugin.bundle/Contents/Frameworks/libswiftFoundation.dylib
/Volumes/1/MyPlugin.bundle/Contents/Info.plist


Here's the Info.plist.
/ It looks exactly the same as the Info.plist file in a bundle in which I have removed all Swift code (so that bundle no longer contains the Frameworks directory) and in which the notarization works as expected - it gets notarized and makes Gatekeepr happy. /

% cat Info.plist
<?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>BuildMachineOSBuild</key>
  <string>18G3020</string>
  <key>CFBundleDevelopmentRegion</key>
  <string>en</string>
  <key>CFBundleExecutable</key>
  <string>MyPlugin</string>
  <key>CFBundleIdentifier</key>
  <string>com.MyPlugin</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleName</key>
  <string>MyPlugin</string>
  <key>CFBundleShortVersionString</key>
  <string>1.0</string>
  <key>CFBundleSignature</key>
  <string>????</string>
  <key>CFBundleSupportedPlatforms</key>
  <array>
  <string>MacOSX</string>
  </array>
  <key>CFBundleVersion</key>
  <string>1</string>
  <key>DTCompiler</key>
  <string>com.apple.compilers.llvm.clang.1_0</string>
  <key>DTPlatformBuild</key>
  <string>11C504</string>
  <key>DTPlatformVersion</key>
  <string>GM</string>
  <key>DTSDKBuild</key>
  <string>19B90</string>
  <key>DTSDKName</key>
  <string>macosx10.15</string>
  <key>DTXcode</key>
  <string>1130</string>
  <key>DTXcodeBuild</key>
  <string>11C504</string>
  <key>LSMinimumSystemVersion</key>
  <string>10.14</string>
  <key>NSPrincipalClass</key>
  <string>MyPlugin</string>
</dict>
</plist>

Hmmm, it’s seems that something in your bundle is making the notary service grumpy. I looked through the info you posted and I can’t see anything obvious. My advice is that you start iteratively bringing your working and non-working cases closer together until you isolate the problem.

If you need help with that, you should open a DTS tech support incident, which will give me a chance to look at your issue in depth.

Also, I noticed that

LSMinimumSystemVersion
is only 10.14. If you raise it to 10.14.4, you can get rid of the bundled Swift runtime completely. This simplifies your code signing and notarisation, and also avoids any possibility of a Swift runtime conflict within your host app.

Share and Enjoy

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

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

Maybe go back to the issue of notarizing each dylib individually. Perhaps you are doing something to corrupt them or the executable. The past couple of notarization problems that I've looked at have been caused by people doing things that are just really off-the-wall. In one instance, someone was using the command-line zip tool to unzip their own submission via altool, thereby corrupting it. In another case, someone was essentially creating their own framework format. In addition, all of their dylibs had invalid rpath paths embedded in them. I was able to reorganize the project into a proper app and get it notarized, but it failed to launch with what looked like a gatekeeper failure. But it was more of an initial loadability check that was failing.


Are you doing something to those dylibs? Does your bundle "executable" have valid rpaths? You can check this with "otool -l".


It looks like there is a big discrepancy between what kinds of executables a Mac will run when notarization is out of the picture, and what is necessary to pass both notarization and initial gatekeeper checks. People have become very invested in, and attached to, some crazy build practices and now notarization is breaking it. But they never should have been doing that stuff to begin with. I can't be any more specific about what "that stuff" might be. In ever single case that I've seen, it's always "You're doing what? Why?"


In your case, your plugin bundle is complicating things. Have you tried running Console.app just before trying to load your plug-in? In the case above, I was able to get meaningful information about of Console. It was XProtectService that reported the problem with the rpath.

The plug-in is built solely by Xcode itself. There is no script outside of Xcode nor there are "complications" intentionally added into the built process. I just call xcode archive. If theres anything non-standard or not-recommended, please, let me know what, ideally with tips how to correct it. Thanks.


There are 5 build phases in Xcode:

Dependencies (0 items)
Compile sources (x items - m and swift files)
Link Binary With Libraries (2 items - Swift and the host app SDK)
Copy Bundle Resources (x items - pdf, xib, pem, pch)
Copy Files (0 items)


These are Release's Build Settings (I've copied everything from Build Settings - Customized - Combined):

COMBINE_HIDPI_IMAGES = YES
DSTROOT = (-PathWhereHostAppExpectsPlugins-)
INSTALL_PATH = /
MACOSX_DEPLOYMENT_TARGET = 10.14
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @loader_path/../Frameworks
DEFINES_MODULE = YES
INFOPLIST_FILE = $(SRCROOT)/MyPlugin/Info.plist
PRODUCT_BUNDLE_IDENTIFIER = com.MyPlugin
PRODUCT_NAME = $(TARGET_NAME)
WRAPPER_EXTENSION = bundle
FRAMEWORK_SEARCH_PATHS = $(SYSTEM_APPS_DIR)/(-HostApp-).app/Contents/Frameworks
CODE_SIGN_IDENTITY = Developer ID Application
CODE_SIGN_STYLE = Manual
DEVELOPMENT_TEAM = (-TeamID-)
ENABLE_HARDENED_RUNTIME = YES
PROVISIONING_PROFILE_SPECIFIER =
GCC_PREFIX_HEADER = MyPlugin/MyPlugin-Prefix.pch
CLANG_ENABLE_MODULES = YES
SWIFT_OBJC_BRIDGING_HEADER = MyPlugin/MyPlugin-Bridging-Header.h
SWIFT_VERSION = 5.0
SWIFT_INCLUDE_PATHS =


Here's what otool prints out (LC_LOAD_DYLIB and LC_RPATH only):

Load command 9
          cmd LC_LOAD_DYLIB
      cmdsize 80
         name @rpath/(-HostApp-).framework/Versions/A/(-HostApp-)Core (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 0.0.0
compatibility version 1.0.0
Load command 10
          cmd LC_LOAD_DYLIB
      cmdsize 88
         name /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 23.0.0
compatibility version 1.0.0
Load command 11
          cmd LC_LOAD_DYLIB
      cmdsize 96
         name /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1673.126.0
compatibility version 300.0.0
Load command 12
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libobjc.A.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 228.0.0
compatibility version 1.0.0
Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1281.0.0
compatibility version 1.0.0
Load command 14
          cmd LC_LOAD_DYLIB
      cmdsize 88
         name /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1894.10.126
compatibility version 45.0.0
Load command 15
          cmd LC_LOAD_DYLIB
      cmdsize 104
         name /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1673.126.0
compatibility version 150.0.0
Load command 16
          cmd LC_LOAD_DYLIB
      cmdsize 104
         name /System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1348.12.4
compatibility version 64.0.0
Load command 17
          cmd LC_LOAD_DYLIB
      cmdsize 96
         name /System/Library/Frameworks/Security.framework/Versions/A/Security (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 59306.41.2
compatibility version 1.0.0
Load command 18
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name @rpath/libswiftCore.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1100.8.255
compatibility version 1.0.0
Load command 19
          cmd LC_LOAD_DYLIB
      cmdsize 64
         name @rpath/libswiftCoreGraphics.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 0.0.0
compatibility version 1.0.0
Load command 20
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name @rpath/libswiftFoundation.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 0.0.0
compatibility version 1.0.0
Load command 21
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name @rpath/libswiftObjectiveC.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 0.0.0
compatibility version 1.0.0
Load command 22
          cmd LC_RPATH
      cmdsize 32
         path /usr/lib/swift (offset 12)
Load command 23
          cmd LC_RPATH
      cmdsize 48
         path @executable_path/../Frameworks (offset 12)
Load command 24
          cmd LC_RPATH
      cmdsize 40
         path @loader_path/../Frameworks (offset 12)


Is everything as expected? What other places to look else for potential issues?

I've tried to set the deployment target to 14.4.4. Yes, the Swift's dylibs disappeard from the bundle but the notarization log still misses include the overall bundle in the list.

OK. This is different. I read your original post again. Can you clarify a couple of things?


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


How did you pack it? Are you distributing it as a pkg file?


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


Did you run the host application first?


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


Where is that?


Here are some possible complications...

4. You are not running the host app first. Therefore, the host hasn't passed Gatekeeper yet. There could be some extra checks as part of the initial Gatekeeper check that are failing due to your differently-signed plug-in that is being loaded.

5. Maybe the host application is doing it wrong. Maybe it is asking you to install the plugin inside its app bundle, thus invalidating its signature. And/or some of 4) above is still complicating things.

3. Are you distributing this as a pkg file? If so, you could just run your fix as part of a post-install script. If not, you would write a custom installer (maybe even in AppleScript) that performs those tasks, in addition to installing the plugin.


After a bit more research, I went ahead and tracked down the host. You didn't redact it well enough. Points 4) and 3) above are still valid. I noticed the following additional issues:

1) The host app has its own plugin manager. When it downloads plugins, their signatures may be invalid or might not even exist. This may cause problems for said host app in the future. Apple has said that unsigned code will not run by default in a future version of macOS. But that's not your problem.

2) Again, revisit how those Apple dylibs are getting into your bundle. Are you still codesigning and notarizing them? What if you don't do that?

3) The host app provides some templates and instructions. Are you using those? Specifically, the instructions tell you to use the "--deep" flag on the codesign. That flag is frowned upon, but you might need it in this case, assuming 2) above doesn't fix it.


I think eskimo's suggestion to set your deployment to 10.14.4 and omit those dylibs is probably the easiest solution. That will make your plug in available. In this market, there are likely some people running old versions so this might actually be a problem for you.


If all else fails, you can use your original hack inside a pkg installer for now.


Edited: The host app seems to be doing everything properly. I used:

codesign -d --entitlements :- /path/to/app


and the correct entitlements are there:

<?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.automation.apple-events</key>

<true/>

<key>com.apple.security.cs.allow-unsigned-executable-memory</key>

<true/>

<key>com.apple.security.cs.disable-library-validation</key>

<true/>

<key>com.apple.security.personal-information.addressbook</key>

<true/>

</dict>

</plist>

First of all, I am going to summarize recent findings:


  • The notarization service does not include the overall bundle in the ticketContents list so it does not recognize the overall bundle as a candidate for notarization. It lists just the dylib files and the main executable. As said by eskimo, the overall bundle should be listed as well.
  • The dylib files themself do not seem to be the issue - I've changed deployment target to 14.4.4 so the swift's dylib files were no longer put into the bundle. The notarization service still did not included the overall bundle in the ticketContents list.
  • Sending dmg instead of zip to the notarization service result in no change (except of including the dmg file in the ticketContents list). The overall bundle ticket is still missing.

As long as the eskimo is right that the overall bundle should be included in the ticketContents list, it seems that something is causing the notarization service to skip the overall bundle.


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


How did you pack it? Are you distributing it as a pkg file?


For the sake of these tests, I were transfering the same zip file as was sent to the notarization service.

When distributing to real users, the bundle is copied in a directory next to several other files, than tar-ed and gzip-ed. The server replaces a content of one "other" file found in the archive before serving it to the user while keeping other file entries intact in the stream. Little complicated but there is no known issue with this approach yet.


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


Did you run the host application first?


It does not matter. I've tried both variants.


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


Where is that?


~/Library/Application Support/TheApp/Plugins


4. You are not running the host app first. Therefore, the host hasn't passed Gatekeeper yet. There could be some extra checks as part of the initial Gatekeeper check that are failing due to your differently-signed plug-in that is being loaded.


The failure appears on subsequent app starts as well.


3. Are you distributing this as a pkg file? If so, you could just run your fix as part of a post-install script. If not, you would write a custom installer (maybe even in AppleScript) that performs those tasks, in addition to installing the plugin.

1) The host app has its own plugin manager. When it downloads plugins, their signatures may be invalid or might not even exist. This may cause problems for said host app in the future. Apple has said that unsigned code will not run by default in a future version of macOS. But that's not your problem.


We are not distributing the plugin via the plugin manager (yet).

The user downloads the plugin from our website, uncompresses and double clicks on the bundle. This starts the host app (as the host app registers itself as a handler to that file extension) and the host app copies the bundle to its plugins folder located inside its Application Support subdirectory. On start-up, the host app tries to load all the bundles presents in that directory.


2) Again, revisit how those Apple dylibs are getting into your bundle. Are you still codesigning and notarizing them? What if you don't do that?


I were not codesigning and notarizing the dylib files in subsequent tests. I built the app to a new separate xcarchive for subsequent tests to have a clear starting point.


3) The host app provides some templates and instructions. Are you using those? Specifically, the instructions tell you to use the "--deep" flag on the codesign. That flag is frowned upon, but you might need it in this case, assuming 2) above doesn't fix it.


I've tried running codesign command initially as well. Now I let the Xcode to codesign (it did some codesigning as part of xcode archive).


I think eskimo's suggestion to set your deployment to 10.14.4 and omit those dylibs is probably the easiest solution. That will make your plug in available. In this market, there are likely some people running old versions so this might actually be a problem for you.


It did not help. I have not tried to run it yet but I followed eskimo's answer that the overall bundle should be listed in the notarization log. So I'm checking the log whether the overall bundle entry appeared.

For the sake of these tests, I were transfering the same zip file as was sent to the notarization service.


Did you staple the bundle? Normally, after sending that zip file to the notarization service, your next step should be to delete that zip. You don't want it. Its only purpose is to upload the bundle. Once notarization succeeds, you staple the ticket to your bundle, as described in the documentation: Customizing the Notarization Workflow. Then you create a new zip file and distribute that.


I'm not sure what eskimo was saying above about those container formats not supporting stapling. I assume he was referring to tarballs and zipfiles. I'm not familiar with plugins, but as far as I know, they can, and should, be stapled.


I don't know about the overall container. The only time I ever check notarization logs is when looking at other people's notarization problems here in the forums. You didn't say how you originally built this project. Did you use the host app's plug-in template? Did you use a plug-in template? I've never tried a plugin and there are many potential differences between your project and the one that eskimo tried.


Lacking any additional information, it looks like you just weren't stapling the bundle. Try that. If it doesnt' work, review the docs again, and review the host app's docs and templates again.

OK, so that confirms that the Swift libraries aren’t the problem. The next step is to determine whether it’s the

Info.plist
or the contents of the bundle. If you replace your product bundle’s
Info.plist
with the one from your working test bundle, does that notarise? [You’ll have to adjust the
CFBundleExecutable
value, obviously.]

Share and Enjoy

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

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

The Info.plist files are identical.


Both working and non-working versions are from the same code base. I've just deleted all Swift files, the Swift-ObjectiveC bridging header file and the part of Objective-C code calling the Swift code. I did no other change - neither in the project metadata, all potential metadata/setting changes were made automatically by Xcode because there was no longer any Swift code in the project so the Swift-related options disappeared. However, the Info.plist file is identical.

OK then, I’ve got nothing. At this point I’m going to fall back to what I wrote yesterday: You should open a DTS tech support incident so that can look at your setup in detail.

Share and Enjoy

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

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

I'm not stappling during these tests. I understand from the docs that stappling is meant mainly for offline purposes, otherwise, online checks are equal to stappling.


Edit: I found the reason. Check my last reply to Eskimo. Thanks for your collaboration in triggering this issue.

Accepted Answer

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.

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