Why Gatekeeper says your app is damaged, and how to fix it
Updated · Dmytro Virych
Guide · 3 min read
Gatekeeper's "damaged and can't be opened" message almost always means a broken or incomplete code signature, not a corrupted download — running codesign -vvv --deep --strict and spctl -vvv --assess --type exec on the app shows exactly which check failed.
Your app opened fine on your own Mac. Then a buyer downloads it, double-clicks it, and macOS refuses outright — the dialog says the app is damaged and belongs in the Trash. That is not Apple reporting malware. It is Gatekeeper reporting that a code-signature check failed, and the fix is almost never re-downloading the app. It is finding which check failed and re-signing correctly.
Apple documents the checks its own notary service runs, in order, in
Resolving common notarization issues.
Run the build through the same checks yourself with codesign and spctl
before you ship the next one.
Is the signature actually valid?
Start here. If you modified the app bundle after signing it — repacked it
into a different disk-image tool, dropped an update in place, edited
Info.plist — the signature no longer matches the bundle. Apple's
troubleshooting page is direct about the result: without a valid signature,
"notarization fails with the following message: The signature of the binary is invalid."
Check it the same way the notary service does:
codesign -vvv --deep --strict /path/to/YourApp.app
Apple's own description of the three flags: vvv performs "a verification
with elevated verbosity," deep ensures "the utility checks nested code
content," and strict "increases the restrictiveness of the validation to
match that required by notarization." A clean signature reports no problems;
a broken one names the exact nested binary — a helper tool, a framework, an
XPC service — that no longer matches what was signed.
Did you sign with the right kind of certificate?
A Mac App Distribution certificate, or a self-signed one, produces something that looks signed but that Gatekeeper will not accept for software distributed outside the App Store: "The binary is not signed with a valid Developer ID certificate." Sign apps, command-line tools and disk images with a Developer ID Application certificate; sign installer packages separately with a Developer ID Installer certificate.
Does the signature actually carry a secure timestamp?
Xcode only adds a secure timestamp during its archive and export workflows.
A custom export step — a hand-rolled build script, a CI pipeline that calls
codesign directly — can skip it, and Apple's notary service then reports
"The signature does not include a secure timestamp." Check for one directly:
codesign -dvv /path/to/YourApp.app
Apple's read on the output: a signature with a secure timestamp shows a
Timestamp line with a date, while "the presence of Signed Time in the
output indicates the binary doesn't have a secure timestamp" instead.
Getting a timestamp means the signing machine has to reach
timestamp.apple.com at the moment it signs — a CI runner with restricted
outbound access at that step produces exactly this failure, and nothing else
in the build looks wrong.
Is the hardened runtime actually turned on?
Signing through Xcode's standard export enables it by default. A custom
codesign invocation that leaves it off gets "The executable does not have
the hardened runtime enabled." Add it explicitly if you sign outside Xcode:
codesign --options=runtime --timestamp \
-s "Developer ID Application: Your Name (TEAMID)" \
/path/to/YourApp.app
Will Gatekeeper actually let it run?
codesign only confirms the signature is well-formed. spctl answers the
question that actually matters to a customer: what will Gatekeeper decide on
their Mac, right now. Apple describes it as checking "if the software to be
notarized will run with the system policies currently in effect":
spctl -vvv --assess --type exec /path/to/YourApp.app
Add --raw for the full verdict as a property list, including which
requirement failed.
The order to check things in
Work top to bottom — a broken signature hides everything downstream, since
spctl cannot assess code it cannot first verify:
codesign -vvv --deep --strict— is the signature valid at all?- Was it signed with a Developer ID Application or Installer certificate, not a Mac App Distribution or self-signed one?
codesign -dvv— does the output show aTimestamp, not just aSigned Time?- Is the hardened runtime enabled (
--options=runtime)? spctl -vvv --assess --type exec— does Gatekeeper's own policy engine agree the app is fine?
Fix the first failure, re-sign, and re-run the same command before moving to the next one. Each of these is a real message from the notary service, not a guess — a build that clears all five is a build Gatekeeper has no signature problem left to call damaged over.
Related
- Notarization rejected? How to read the notarytool log
- What does stapling a notarization ticket actually do?
- Do you need to notarize a Mac app you sell yourself?