4

Our app has been code signed. Our Apple certificate is up to date. Previous versions of our app have run just fine.

However, when the DMG is downloaded by the users, on some Macs the application is quarantined, but for the majority of users, it's not. So some users can open the app and others get the "X.app can’t be opened because the identity of the developer cannot be confirmed."

Luckily I have 2 Macs here that have the quarantine problem, but we can't find a difference between these Macs and the others. Has anyone else run into this problem?

2 Answers2

12

I think you may be a bit confused about how quarantine, code signing, and Gatekeeper work. The error you're seeing is from Gatekeeper, and indicates two different (and independent) things: 1) the app is quarantined (which has to do with how it was downloaded, not how it's signed) and 2) it is not signed in a way that complies with the Gatekeeper policy defined in Security & Privacy preferences. Let me explain these two things in more detail.

  • Quarantine is a result of the app (or the disk image it was in) being downloaded. When you download a file with a browser, the browser will attach a com.apple.quarantine attribute to it, indicating that it came from an untrusted network source. Other types of internet apps (email, chat, etc) should also attach this attribute to downloaded files.

    But not all network download methods will apply the quarantine attribute. For example, copying a file over a file sharing connection (e.g. AFP or SMB) with the Finder will not mark it as being in quarantine. Also, command-line tools like curl and wget won't apply quarantine.

    In your case, when you download the .dmg file, it gets marked as quarantined; when you open it, the attribute gets propagated to its contents, so the app is also marked as being in quarantine (and if you copy it to /Applications, the quarantine attribute gets copied along with everything else).

    To check whether a file is quarantined, use ls -l@ on it and look for the com.apple.quarantine attribute. It's entirely possible that the difference you're seeing between different computers has to do with how the disk image was downloaded and therefore whether the apps are quarantined.

  • When you open a quarantined app, Gatekeeper checks to see whether it complies with you computer's security policy subsystem. This is where code signing comes into it. You can view and change your policy in System Preferences -> Security & Privacy pane -> General tab -> "Allow apps downloaded from" or with the spctl command-line tool. The default policy is to allow quarantined apps that are from the Mac App Store (i.e. signed with Apple's app store keys) or from an identified developer (i.e. signed with a developer ID key issued by Apple to a registered developer).

    When you try to open an app that's quarantined, and not signed in a way that complies with this policy, you get an error saying that "X.app cannot be opened because it is from an unidentified developer" or "... was not downloaded from the Mac App Store." If it's quarantined but does comply with the policy, you get a message that "X.app is an application downloaded from the internet. Are you sure you want to open it?" (with an Open button available). If it's not quarantined, the check is not performed, and the app opens directly.

    You can get more information about the code signing and policy status of an application with spctl --assess -vv /path/to/X.app (which'll tell you whether it complies with the Gatekeeper policy) and codesign -dvv /path/to/X.app.

In summary, quarantine is normal and you should expect your users to experience it (and if you're not seeing it on one of your test computers, there's something wrong with how you're testing). Gatekeeper errors depend on both proper signing (check with codesign and spctl) and the Gatekeeper policy settings on the computer; check both to see what's going on.

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
  • Thanks for the detailed reply. All of the tools show that the app is indeed signed. Here's what I get using each of the options (app name and team ID have been changed)... – ColonelPanik Jun 15 '16 at 17:21
  • $ spctl --assess -vv MyApp.app MyApp.app: accepted source=Developer ID origin=Developer ID Application: RT Ltd. (ABCDEF1234) $ codesign --verify --deep --verbose=2 MyApp.app MyApp.app: valid on disk MyApp.app: satisfies its Designated Requirement – ColonelPanik Jun 15 '16 at 17:27
  • @user3140551: I'm running out of ideas, but here are a couple more: does `codesign -dvv` show "Sealed Resources version=2"? If not, the signature is in an obsolete format. Also, are there any unsigned/improperly signed dependencies (frameworks, etc) that your app uses? See [this question](http://stackoverflow.com/questions/31709087/failure-digitally-signing-a-mac-app-outside-xcode/32025478#32025478) for an example... – Gordon Davisson Jun 16 '16 at 15:45
  • I get this: Sealed Resources version=2 rules=12 files=294, and I believe the dependencies are signed. There are no warnings. We're in the middle of a new dev cycle, so we'll return to the issue with the new release. Thanks for your help, I've bookmarked that link. If we figure it out in the meantime, I'll post the answer. – ColonelPanik Jun 17 '16 at 16:49
2

Gordon Davissons answer is quite extensive and should help in most cases. In my case, it did not.

Besides the two gatekeeper error messages that he mentions, there is a third one and that is the one from your question:

".app can’t be opened because the identity of the developer cannot be confirmed."

In my case this message came up, when an embedded third party framework had a bad run path setting: LD_RUNPATH_SEARCH_PATHS in build settings did reference something that it was not allowed to.

Apple documents this here https://developer.apple.com/library/content/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG207

If an app uses @rpath or an absolute path to link to a dynamic library outside of the app, the app will be rejected by Gatekeeper.

And they even state:

Neither the codesign nor the spctl tool will show the error. The error will only appear in the system log.

The solution was to modify the third party framework to something standard like this:

$(inherited) @executable_path/../Frameworks @loader_path/Frameworks

Klaas
  • 22,394
  • 11
  • 96
  • 107