I've just built an app, signed it with my Developer ID certificate, and had it successfully notarized. However, when I download a zipped copy of the app in macOS 10.15.5 and try to run it, I get the "“XYZ” can’t be opened because Apple cannot check it for malicious software" error message. The same zip file works fine in 10.14.6 and earlier.
All of the usual checks to make sure the app is signed and notarized properly report that it is:
% codesign --verbose --verify XYZ.app
XYZ.app: valid on disk
XYZ.app: satisfies its Designated Requirement
% xcrun stapler validate XYZ.app
Processing: /path/to/XYZ.app
The validate action worked!
% spctl --assess --verbose XYZ.app
XYZ.app: accepted
source=Notarized Developer ID
Previous versions of the app had no issue with notarization. I haven't changed anything significant in the app since its last release, aside from a few bugfixes, nor have I changed the method I use to sign or notarize it.
What's going wrong? I've had so many headaches due to the new notarization requirement, so I'm quite dismayed I've run into another one. And due to the black-box nature of notarizing there's no way for me to figure out what's going wrong other than to ask here!
After opening a TSI, eskimo was able to help me sort out what I was doing wrong. (Thanks!)
The issue was that the scripts I wrote for zipping an app to send to Apple's notary service had a fatal (and apparently common) bug. I was using ditto like so to zip the app:
ditto -ck -rsrc --sequesterRsrc /path/to/myApplication.app
What's missing is the --keepParent option. It should have been this:
ditto -ck -rsrc --sequesterRsrc --keepParent /path/to/myApplication.app
Without --keepParent the topmost directory in the zip will be "Contents" rather than "myApplication.app", and the ticket won't contain cdhashes for anything except the app's main executable.
Hopefully this thread will allow other people to avoid this pitfall in the future!
And I do sincerely hope that Apple will improve their command line tools and the console output from Gatekeeper to make this sort of issue much easier to debug. If Gatekeeper's output had said something to the effect of "xyz framework in myApplication.app is not included in its ticket" or if xcrun's stapler command issued a warning saying the ticket didn't include any of its frameworks or dylibs then it's much more likely I could have figured this out on my own.