Mounting a Notarized DMG via hdiutil while Offline

I was reading through this post:

https://developer.apple.com/forums/thread/718583

I've been able to reproduce this behavior by double-clicking a DMG in the Finder while the Mac is Offline. I checked the Notarization status of the app via spctl and it shows "Notarized Developer ID". So sure enough, Quinn's comment about Gatekeeper "ingesting" the notarization ticket stapled to the DMG and automatically applying it to the app inside is 100% spot-on.

However, I can't seem to get the same behavior to happen when mounting the DMG via hdiutil in Terminal. While Offline, I do a:

hdiutil attach /path/to/my/dmg.dmg

and then

spctl -a -t exec -vvv /Volumes/path/to/my/mounted/dmg/myapp.app

After the spctl I'm seeing

/Volumes/path/to/my/mounted/dmg/myapp.app: rejected
source=Unnotarized Developer ID
origin=Developer ID Application: My Developer Creds (XXXXXXXXXX)

Is there a way to get Gatekeeper to "ingest" the notarization ticket stapled to the DMG when using hdiutil while Offline?

Note 1: If I use hdiutil while online, everything works as expected. Note 2: I'm testing all this via a VM of macOS 12.7.1, if that makes any difference.

Thanks!

Accepted Reply

Yes, using "open" works

Yeah, that’s what I thought.

For Gatekeeper to ingest your ticket it must evaluate your product. When you run open, it opens the disk image using NSWorkspace which does a basic Gatekeeper check on it, which triggers that ingestion. This doesn’t happen when you mount it with hdiutil.

From there we copy the app inside using NSFileManager.

If it’s an app you could avoid this problem by:

  1. Siging your app.

  2. Notarising your app.

  3. Stapling to your app.

  4. Wrapping it in a disk image.

  5. Signing, notarising, and stapling your disk image, or not, as you see fit.

When the user runs your app for the first time, Gatekeeper which ingest the stapled ticket from there.

While I generally recommend that you sign and notarise your disk image, it’s not an absolute requirement [1].

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Exception on some very early releases of… bah… I can’t remember, perhaps 10.15.

Replies

If you mount the image by passing it to open, does that work?

% open /path/to/my/dmg.dmg

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

There are two main methods. Does the following solves your problem?

https://codermite.com/t/executing-shell-commands-like-open-hdiutil-xattr-from-a-swift-application-for-dmg-management-and-notarisation/

Quinn -

Yes, using "open" works:) However we're actually mounting the dmg from within our app, and doing an "hdiutil attach -nobrowse -noautoopen" to keep it off the Desktop. From there we copy the app inside using NSFileManager. Basically, we're trying not to bother our users about it:) So sticking with hdiutil is important.

Paradigm777 -

Wow, that's crazy that someone asked practically the same (very esoteric!) question on Codermite just a few hours after I posted it here. I haven't tried manually setting the Quarantine flag as suggested in that post. It looks like using xattr to do this is a bit tricky, however I think I'll give it a try just to see what happens. But question back to Quinn: How "safe" would it be to manually set the Qurantine flag, in an attempt to trigger Gatekeeper's "ticket ingestion"?

Without going into too many gory details, the reason I'm looking into this is that our systems currently do a two-pass Notarization: App first, build the dmg, then Notarize the dmg. It'd be nice if we could skip the first Notarization step and just stick with Notarizing the dmg. But we could certainly just stick with a two-pass Notarization system and call it a day:)

Unfortunately I can't seem to use xattr -w com.apple.quarantine "..." /Volumes/path/to/my/mounted/dmg/myapp.app to trigger Gatekeeper. Xattr doesn't like that our DMG's are all re-only. Sigh.

I think I may need to stick with hdiutil and just continue with our existing two-pass Notarizing system.

Yes, using "open" works

Yeah, that’s what I thought.

For Gatekeeper to ingest your ticket it must evaluate your product. When you run open, it opens the disk image using NSWorkspace which does a basic Gatekeeper check on it, which triggers that ingestion. This doesn’t happen when you mount it with hdiutil.

From there we copy the app inside using NSFileManager.

If it’s an app you could avoid this problem by:

  1. Siging your app.

  2. Notarising your app.

  3. Stapling to your app.

  4. Wrapping it in a disk image.

  5. Signing, notarising, and stapling your disk image, or not, as you see fit.

When the user runs your app for the first time, Gatekeeper which ingest the stapled ticket from there.

While I generally recommend that you sign and notarise your disk image, it’s not an absolute requirement [1].

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Exception on some very early releases of… bah… I can’t remember, perhaps 10.15.

If it’s an app you could avoid this problem by:

  1. Siging your app.
  2. Notarising your app.
  3. Stapling to your app.
  4. Wrapping it in a disk image.
  5. Signing, notarising, and stapling your disk image, or not, as you see fit.

Yup, that's exactly what we do. We'll just keep on doing that. Thanks Quinn.