Notarizing a package/pkg with multiple libraries and bundles

We have a set of questions about Notarization. We create plug-ins for various 3rd party software. Our plug-ins operate under the 3rd party software. So for example Photoshop (our is not a typical Mac App store app - we make these also so we know how Mac App store code-signing etc works).


Our infrasturcture is something like "plug-ins" for each version of Photoshop we support (which gets installed in the Photoshop plug-ins folder). Then component libraries that are installed in Library/Application Support/OurProduct folder and the Applications folder (we also create a folder in the Applications folder and stick in various other parts and libraries, readme, userguide etc). So its basically a set of libraries really thats all over.


Then we take all of those components and we package (using Package Maker under 10.11.6) it and create flat package installers (which contain installer plug-ins at the end) which we deliver to our end user. The final installer are signed using th Apple 3rd party install certificate.


None of these parts are code-signed as we never had to.


So, we have multiple questions here. Do we have i to codesign each library/plug/bundle/component included in the pkg file? When we submit for notarization, do we just submit the final pkg (the pkg can contain other pkg files) file. Now when the Photoshop plug-in access our other libraries/bundles (they are loaded dynamically) will it cause loading/binding/excution problems?

Replies

Do we have i to codesign each library/plug/bundle/component included in the pkg file?

Yes. All code you distribute to a wide range of users should be signed and notarised. The extent to which the system currently enforces this requirement varies, but our long-term direction is crystal clear.

When we submit for notarization, do we just submit the final pkg (the pkg can contain other pkg files) file.

Yes. Our general guideline is that you notarise the outmost container. So, for example, if you had a

.app
, within a
.pkg
, within a
.dmg
, you’d notarise the
.dmg
.

Now when the Photoshop plug-in access our other libraries/bundles (they are loaded dynamically) will it cause loading/binding/excution problems?

That depends. If the app has library validation enabled (either through some legacy mechanism or by enabling the hardened runtime), it will only be able to load code that’s signed by Apple and by that app’s Team ID. This would block your code. However, most apps that support an in-process plug-in model do not have library validation turned on, and thus this won’t be an issue.

You’ll have to work with your host app vendors to ensure that they specifically allow this in-process plug-in model to continue working. The host app will eventually have to enable the hardened runtime in order to be notarised. When it does this, it opts in to library validation by default, and it must opt out of that if it wants to continue supporting in-process plug-ins. It can do this using the Disable Library Validation entitlement (

com.apple.security.cs.disable-library-validation
).

The host app may want to take other action as well. If you search Notarizing Your App Before Distribution and Resolving Common Notarization Issues for plug-in, there’s a bunch of hints there. These aren’t targeted at plug-in developers directly, but you should take the time to understand this stuff so that you can advise any host app developers you talk to.

Share and Enjoy

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

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

HI Quinn,


Thank you for explaining in detail and yes this is all helpful. Now we have an additional question.


Our Photoshop plug-in launches an external backround application that creates files and then passes these files back to the host Photoshop plug-in; which then passes it back to Phostoshop We've realized that this is causing a crash right now. Is this because of some kind of code-signing/security scope? Are we missing something?

Is this because of some kind of code-signing/security scope?

It’s hard to say based on the info you’ve posted. How about we start with a symbolicated crash report, eh?

When you post the crash report, use the

<>
icon to format it as code. Don’t worry if it requires moderation; I can take care of that. Make sure that it’s symbolicated. See Technote 2151 Understanding and Analyzing iOS Application Crash Reports for details on that.

Share and Enjoy

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

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

Hi Quinn,


Thanks for your response. After I wrote the above we started testing with some of our newer builds (where we had migrated code out of fsref and some other older API's that are marked deprecated) and the crash is gone. So maybe the fsref and migrating out of older SDK (less than 10.9) helped?


We have one final question. Because our components are mainly dylibs, bundles etc, we have resources that reside outside the dylibs and we store these as zipped data (not code but data fork .rsrc). As these zip's can't be codesigned, we presume it wont cause any kind of notarization issue? Its just data that is loaded by the dylibs for usage.

As these zip's can't be codesigned, we presume it wont cause any kind of notarization issue?

It’s true that the trusted execution system won’t block you loading unsigned data. However, I’m curious why you’re taking this approach. If the data is tied to your executable, you should include it in the executable’s bundle. For a dynamic library (

.dylib
), which doesn’t have a bundle, you can switch to shipping it as a framework. That way your entire product will be protected by the code signatures on the various bundles, which is what you should be aiming for security-wise.

Share and Enjoy

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

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

Hi Quinn,


Again thank you for your insight. Its just a legacy system thats carried forward (the dylib/resource issue) in a straight forward fashion. We expect to move these to a framework in the future (we have a lot of legacy code that we've migrated forward over the years and bits remain). This probably is one of the last pieces of the migration puzzle we have for the future.


Also, we were able to notarize/run our latest builds without a hitch (so everything seems to be in place) and in testing these builds out we've understood that when our "external app" which is a helper to the Photoshop plug-in starts read/writing files outside of the Documents folder, the macOS 10.15 security framework kicks in asking whether to grant read/write access across the network/certain directories etc. We presume this is an entitlement issue during codesigning? Is there a univeral file read/write entitlement so that we can stop this? Or is this part of how things are going to work?

when our "external app" which is a helper to the Photoshop plug-in starts read/writing files outside of the Documents folder, the macOS 10.15 security framework kicks in asking whether to grant read/write access

The answer here depends on whether your helper app has the App Sandbox enabled or not. If you run this over the built binary:

$ codesign -d --entitlements :- /path/to/your/helper.app

what does it show?

Share and Enjoy

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

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

Hi Quinn,


App Sanbox is not enabled and there are no entitlements that show up. Are we supposed to use the App Sandbox entitlement? There is no open/save dialog our external helper app presents (its there so invoke some libraries and act as a bridge).


Because the app is an external process (outside of the Photoshop plug-in) it's in it own process space (this is to protect Photoshop in case our app an any components it utilizes crashes). We don't think entitlements carry across the process boundaries (Photoshop's entitlements are propogated to the plug-ins but for an external helper app that is not part of the plug-in itself).

App Sanbox is not enabled and there are no entitlements that show up.

OK.

Are we supposed to use the App Sandbox entitlement?

I wasn’t suggesting that, but rather asking a question about how things are currently set up.

We don't think entitlements carry across the process boundaries

That depends on how the process is launched. If the new process is a child process — for example, the parent process launches it with

NSTask
— it will inherit entitlements from the parent. However, that assumes that this is an entitlements issue, which I don’t think it is. Rather, I think you’re hitting a user data protection check.

When you wrote:

when our "external app" which is a helper to the Photoshop plug-in starts read/writing files outside of the Documents folder

Did you mean “inside the Documents folder”? macOS 10.15 beta has new user data protections checks for the desktop, Documents and Downloads directories. WWDC 2019 Session 701 Advances in macOS Security has all the details on those.

Share and Enjoy

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

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

Hi Quinn,


That would be outside the Documents folder. Someone can for example obtain/reference a file from a mounted network server disk or choose to specify files be saved to a location outside the Documents folder (Desktop for example). Because our helper app is outside of the plug-in scope (its not a child process; though making it a child process may actually be something we could consider), its launched via launchApplication). Thank you for the link to the Advances in macOS security.

Hi Quinn,


very similar situation here – I develop Photoshop panels (which are basically web applications, that may or may not include actual Photoshop plugins written in C++).

I am building an installer.pkg via Packages (by WhiteBox) in charge of the actual files deployment, that in turn is wrapped with a product.dmg that gathers: the installer.pkg, plus an uninstaller.app (an app-ified AppleScript) plus some .pdf documentation. The .dmg is what the user downloads (from my own store).


A couple of questions:

  • Could you please confirm that the outer .dmg is the only one in need to be notarized?
  • Besides notarization, at the moment, I'm signing them all: the .pkg, the uninstaller.app and the .dmg – is this a good practice or redundant?


Thank you very much!


Davide Barranca

Could you please confirm that the outer

.dmg
is the only one in need to be notarized?

That’s correct.

Besides notarization, at the moment, I'm signing them all: the

.pkg
, the
uninstaller.app
and the
.dmg
– is this a good practice … ?

Yes. Not just “good practice”, but required. For notarisation to be successful [1], all the code within your product must be signed.

Share and Enjoy

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

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

[1] Well, recent developments mean that notarisation will succeed if you get things wrong, but you’ll get a bunch of warnings and those warnings will eventually turn into errors.

Very kind of you, thanks for confirming!


Davide

Hi,

while discussing with another developer, the following scenario came to our minds.


Say that I have signed .a pkg and .app, wrapped in a notarized/stapled outer dmg, as we've discussed.

What if the user downloads the .dmg and then disconnects from the internet? The notarization ticket is stapled to the dmg, hence it opens successfully... but being him/her offline, what about the .pkg and .app, will they run being signed only without online check for the dmg content? I.e. does Finder recognize that they come from a notarized container? And what if the user copies them from the .dmg to the HD... shouldn't they be individually notarized as well at this point?


I am aware that we're talking really edge cases here, but it'd be nice to know in advance to streamline support calls :-)

Thank you!


Davide

What if the user downloads the

.dmg
and then disconnects from the internet?

When the user mounts the disk image, Gatekeeper checks its code signature. If the disk image has a stapled ticket, the system will ingest it at this point, meaning that the contents of the ticket are available when you open the

.pkg
and run the
.app
, even if the Mac is offline throughout the entire process.

Share and Enjoy

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

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