Send a Mac app to testers: notarization, .dmg vs .pkg and Gatekeeper messages
· 5 min read
Sending a Mac app to testers outside the App Store looks simple: zip it, send a link. Then the first tester writes back that macOS will not open it. On a Mac, Gatekeeper checks every app downloaded from the internet, and what the tester sees depends on how the app was signed, whether Apple notarized it, and how you packaged it. This guide covers the developer side (signing, notarization and stapling), the choice between .dmg, .pkg and a zipped app, and the messages testers see in each case.
Signing and notarization are the developer's job
For apps outside the Mac App Store, Apple expects two things.
- Developer ID signing. Sign the app with a Developer ID Application certificate from your Apple Developer account, with the hardened runtime turned on. A .pkg installer is signed with a separate Developer ID Installer certificate. Apple Development and Apple Distribution certificates are for development and for the Mac App Store, not for handing an app to people on other Macs.
- Notarization. Send the signed app, .dmg or .pkg to Apple's notary service, for example with
xcrun notarytool submit MyApp.dmg --keychain-profile "notary" --wait. Apple checks it for known malicious content and signing problems and, if it passes, records a ticket. - Stapling. Attach that ticket to the file with
xcrun stapler staple MyApp.dmg. Without a stapled ticket, Gatekeeper looks it up online at first launch, which fails on a Mac without a connection. You can staple an .app, a .dmg or a .pkg, but not a .zip: staple the .app first, then zip it.
Xcode does all of this from Organizer with "Direct Distribution". In CI, the same notarytool and stapler commands run after the build.
.dmg, .pkg or a zipped .app
| .dmg | .pkg | Zipped .app | |
|---|---|---|---|
| What the tester does | Opens the disk image and drags the app to Applications | Runs an installer, often with an admin password | Unzips and moves the app to Applications |
| Good for | Most apps: familiar and simple | Apps that install helpers, launch daemons or files outside the app | Quick internal rounds |
| Signing | App with Developer ID Application; sign the .dmg too | Developer ID Installer for the package | App with Developer ID Application |
| Staple | The .dmg | The .pkg | The .app, before zipping |
What testers see
- Signed with Developer ID and notarized: a short prompt that the app was downloaded from the internet and asks whether to open it. One click and it runs.
- Signed but not notarized, or unsigned: on recent macOS, a message that Apple could not verify the app is free of malware, and the app does not open. Since macOS Sequoia, the Control click and Open shortcut no longer gets past it; the tester goes to System Settings, Privacy and Security, and clicks Open Anyway, then confirms with a password.
- "is damaged and can't be opened": usually the signature broke after signing (a file was changed, or the app was copied in a way that dropped parts of it), or the app is only ad hoc signed. Build and sign again rather than asking testers to work around it.
Some teams tell testers to remove the quarantine flag with xattr in Terminal. It works, but it teaches people to switch off a protection; notarizing the build is the better habit.
A short checklist before you send the link
codesign -dv --verbose=4 MyApp.appshows a Developer ID Application signer and the hardened runtime flag.spctl -a -vv MyApp.appreports the app as accepted with a notarized Developer ID source.xcrun stapler validate MyApp.dmgconfirms the ticket is stapled.- The minimum macOS and the architectures (Apple silicon, Intel or both) match the Macs your testers use.
- You opened the downloaded file on a second Mac, not only on the one that built it.
Sharing the build on AppForShare
AppForShare Pro and Team take desktop builds: a .dmg, a .pkg or a zipped .app (a .zip with one top level .app that has Contents/Info.plist). You upload it the same ways as a mobile build, from the web, the CLI, CI or an AI tool through MCP, and get the same link, QR code, release notes, channels, password and link controls.
On a computer the page shows a download button, the size and the SHA-256. A phone that opens the link is told to open the page on a Mac. The page also lists what AppForShare read from the file on its own servers, with no call to Apple:
- bundle ID, version, minimum macOS and architectures;
- the signature: Developer ID, another Apple certificate, ad hoc or unsigned, and the signer;
- whether a notarization ticket is stapled, for a .dmg or a zipped .app (not read for a .pkg).
For a .dmg, the name and version come from the file name, because the disk image contents are not opened, and the page says so. The build page shows signing check lines for an unsigned build, an ad hoc signature, a certificate that is not Developer ID, and a missing notarization ticket, so you see the problem before testers do. Every desktop file also goes through the malware check, like mobile builds.
What AppForShare does not do: sign or notarize your app, or check notarization with Apple. A stapled ticket on the page tells you the ticket is in the file; Gatekeeper on the tester's Mac still makes its own decision.
Common questions
Do testers need an Apple account?
No. A Developer ID signed, notarized app opens on any Mac that meets its minimum macOS.
Can I use TestFlight for Mac instead?
Yes, for builds you upload to App Store Connect. It has its own review for external testers. A notarized .dmg skips that and needs no TestFlight app.
Which plan takes Mac builds on AppForShare?
Pro and Team. Files up to 2 GB on Pro and 4 GB on Team.
More: desktop builds and the desktop builds docs. Shipping a Windows app as well? See send a Windows app to testers.


