How does macOS identify the signing status of an app downloaded from the Internet?

The information is stored within extended attributes, with additional information potentially embedded within an application.

Extended Attributes

This quarantine information is stored as an extended attribute. Use the xattr tool to view the attributes associated with a file or application.

The attribute causing this message is com.apple.quarantine.

See How do I remove the “extended attributes” on a file in Mac OS X? and App can't be opened because it is from an unidentified developer for more details.

Gatekeeper and Code Signatures

The extended attribute is used by Gatekeeper on macOS and is discussed in How to set (restore) the com.apple.quarantine attribute?

A optional digital signature embedded within an application is used to determine the application's developer. If a signature is not found, macOS presents the application as being from an unidentified developer.


In fact the message "Unidentified developer ..." is the result of a combination of both tasks: checking the com.apple.quarantine attribute and the code signing resources (in */Contents/_CodeSignature/CodeResources) while the actual signing status is solely determined by */CodeResources.

You can get the extended attribute by entering:

$ xattr -p com.apple.quarantine /Applications/*.app

The code signing information is accessed by entering:

$ codesign -dvvv /Applications/*.app

Example:

$ codesign -dvvvv /Applications/Google\ Chrome.app/
Executable=/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
Identifier=com.google.Chrome
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20200 size=273 flags=0x800(restrict) hashes=3+3 location=embedded
OSPlatform=36
OSSDKVersion=658432
OSVersionMin=657664
Hash type=sha256 size=32
CandidateCDHash sha1=bc8e3dffe7d9d5242e09ea80a220ed365d46fdf2
CandidateCDHash sha256=d7ae6211906bb17d593ce9c215d190a81f37e658
Hash choices=sha1,sha256
Page size=4096
CDHash=d7ae6211906bb17d593ce9c215d190a81f37e658
Signature size=8949
Authority=Developer ID Application: Google, Inc. (EQHXZ8M8AV)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=20. Mar 2018 at 07:23:20
Info.plist entries=36
TeamIdentifier=EQHXZ8M8AV
Sealed Resources version=2 rules=7 files=203
Internal requirements count=1 size=240

The most important part is the certificate chain (and the chain of trust):

Authority=Developer ID Application: Google, Inc. (EQHXZ8M8AV)
Authority=Developer ID Certification Authority
Authority=Apple Root CA

Here three different authorities are visible:

  1. Root certificate: Apple Root CA
  2. Intermediate Apple developer certificate: Developer ID Certification Authority
  3. Developer certificate: Google, Inc. (EQHXZ8M8AV)

This means that the app is signed with a developer certificate, published and signed by Apple's intermediate developer authority, which itself is published and signed by Apple's Root CA.

This chain qualifies Google (or more exactly: the team/unit Google, Inc. (EQHXZ8M8AV)) as an Apple identified developer.

You can also codesign apps either yourself or with a codesigning certificate from another intermediate/root authority but this won't overcome Gatekeeper.

Now four permutations are possible assuming Gatekeeper is enabled (but not considering self-signing/alien-signing):

  • No com.apple.quarantine attribute/no Apple Developer certificate (Example: brew cask installed Apache CouchDB)
  • No com.apple.quarantine attribute/an Apple Developer certificate (Example: brew cask installed Google Chrome)
  • A com.apple.quarantine attribute/no Apple Developer certificate (Example: Apache CouchDB installed by downloading the zip from the website and copying the unzipped app to /Applications/)
  • A com.apple.quarantine attribute/an Apple Developer certificate (Example: Google Chrome installed by downloading the dmg from the website and copying the app inside to /Applications/)

In the first two cases the app will simply launch. In the third case you will get the Unindentified Developer message. You can resolve this by removing the extended attribute xattr -d com.apple.quarantine * (=case 1). In the fourth case you will get the "* was downloaded from the Internet, are you sure you want to open it?"


How is macOS able to determine this information? Where is the signing metadata for an app stored?

The signature is stored within the application binary itself, with some additional data in the application bundle (in the file Contents/_CodeSignature/CodeResources).

You can get some information on the signature using the command-line utility codesign -- for instance:

# codesign -dv /Applications/Preview.app
Executable=/Applications/Preview.app/Contents/MacOS/Preview
Identifier=com.apple.Preview
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20100 size=21314 flags=0x0(none) hashes=659+5 location=embedded
Platform identifier=4
Signature size=4485
Info.plist entries=35
TeamIdentifier=not set
Sealed Resources version=2 rules=13 files=2077
Internal requirements count=1 size=68