Apparency

Frequently Asked Questions

Installing Apparency

What versions of macOS does Apparency support?

Apparency supports:

Does Apparency automatically check for updates?

Yes, once every 2 weeks — or less, if you use it less often — Apparency will download a small file from our website to get the current version number. If a newer version is available, you'll see an Update Available button on the right side of the app's title bar: available update indication

Click on Update Available to open the Apparency download page, where you can get the latest version.

If you want to change the frequency with which Apparency checks for updates, or turn off automatic checking entirely, use Apparency > Preferences > Update: update pref pane

Apparency never automatically downloads or installs the actual updated app. You make the decision about when or if to download it, and where and how to install it.

Understanding Apparency

Why should I care about these details of an app?

You shouldn't need to care about these details. And maybe you don't need to care about them — that is clearly Apple's position on the matter.

But if you do care about them, shouldn't it be easier to get the information?

Apparency is primarily for people who already know that they wanted something like this. If it doesn't sound like something you want, we won't try to convince you. After all, we make the same $0 whether you use it or not.

“But isn't [security feature X] just more Apple security theater?”

Maybe. Maybe not. But what is theater without an audience? ¯\_(ツ)_/¯

Seriously, we don't claim to be authorities on this. There is no shortage of other people who have opinions on the matter. Apparency simply provides visibility into the mechanisms that exist. You can decide for yourself how much trust to put in them.

“Won't [some command in Terminal] give me the same information?”

Yes, absolutely. There's nothing that Apparency shows that isn't available through some Terminal command or another.

For example, the information about the code signature, entitlements and such can be discovered using the codesign(1) command. But you have to wrangle codesign's arcane command line options, and run it multiple times different ways to get all of the relevant information. If you want Gatekeeper information, you also need to use the spctl(1) command. And if you want to actually examine the signing certificate, you need to grok codesign's --extract-certificates option, hunt down the (buried) Certificate Assistant app, click through its certificate evaluation flow, and drag the extracted certificates into it.

Apparency is simply aiming to make this all easier and more convenient.

Is Apparency “sandboxed”? What entitlements does it have?

Yes, Apparency is sandboxed. In fact, you can easily see this using Apparency itself.

To quickly open Apparency using Apparency, use Cmd-Option-O. You can see that App Sandbox is enabled.

If you use Component > Show Entitlements, you'll see that the top-level Apparency app has the following entitlements:

Entitlements for the Apparency application
Entitlement KeyValueReason
com.apple.security.files.user-selected.read-only YES This allows Apparency to see the app that you tell it to open — even if it's in a place that is not otherwise accessible to sandboxed apps, such as inside your home folder.
com.apple.security.temporary-exception.mach-lookup.global-name com.apple.security.syspolicy This allows Apparency to talk to the /usr/libexec/syspolicyd daemon, which is required to successfully check an app's notarization status. (Apparency uses the macOS Security.framework APIs to check for notarization, but that framework's sandbox configuration isn't complete.)

Within Apparency, there are two other components that are also sandboxed, and thus have explicit entitlements.

The ApparencyPreviewExtension.appex component provides the Quick Look Preview to the Finder, and has the following entitlements:

Entitlements for the ApparencyPreviewExtension.appex component
Entitlement KeyValueReason
com.apple.security.files.user-selected.read-only YES As above, this allows the Quick Look extension to see the app to preview.
com.apple.security.temporary-exception.mach-lookup.global-name com.apple.security.syspolicy As above, this allows the Quick Look extension to check an app's notarization status.
com.apple.security.temporary-exception.sbpl (allow lsopen) On macOS 11 (Big Sur), this allows the Open With Apparency button to work. That button does the equivalent of opening a custom URL, which is handled by the Apparency app. The sandboxing of Quick Look Preview extensions on Big Sur is such that, by default, this operation — opening a URL via LaunchServices — is not allowed.

Finally, under the MRSFoundation.framework component, you'll find a com.mothersruin.MRSFoundation.UpdateCheckingService.xpc XPC service. This is the component that performs the periodic check for updates, and is entitled as follows:

Entitlements for the com.mothersruin.MRSFoundation.UpdateCheckingService.xpc component
Entitlement KeyValueReason
com.apple.security.network.client YES This allows the XPC service to make an outgoing network connection, in order to fetch this file, which contains the information about the current version of Apparency available for download.

Why don't I get a Quick Look preview on macOS 10.15 (Catalina)? What if I prefer the standard preview instead?

Once you've opened Apparency for the first time, macOS ought to enable its Quick Look Preview extension, so that previewing an app from the Finder will show the enhanced version.

However, if you don't get the expected preview, open System Preferences and go to Extensions > Quick Look and make sure Apparency is checked.

If you'd rather not use the Apparency preview — but want to keep the Apparency app — you can disable the previews here as well.

Why isn't Quick Look supported on macOS 10.14 (Mojave)?

In macOS 10.15 (Catalina), Apple introduced a new scheme for apps that want to provide Quick Look previews, and has now “deprecated” the old scheme. These schemes are completely different, so supporting the pre-10.15 scheme would be a lot more work with no future. We are not enthusiastic about such work, even though we are sympathetic to people remaining on macOS 10.14 (Mojave) — especially since we are, too!

Why the name “Apparency” anyway?

It's a portmanteau of “app” and “transparency.”

Yeah, we know, but naming things is hard. At least we didn't give it a name that makes people think it's malware, like last time.

Using Apparency

What do the different Notarization statuses mean?

In the info pane, the Notarization status is described with one of the following:

Notarization StatusDescription
Granted The app or component was submitted to Apple's notarization service and approved for distribution.
Granted — Stapled Ticket The app or component was submitted to Apple's notarization service and approved for distribution, and a notarization ticket was “stapled” to the app. A notarization ticket is cryptographically signed by Apple, and stapling it to the app allows Gatekeeper to verify the notarization, even when your computer isn't connected to the internet. (However, stapling the ticket to the app is not strictly required. Sometimes, the ticket is stapled to the disk image that contains the app: this serves the same purpose but doesn't leave behind a stapled ticket that Apparency will find. If neither is stapled, macOS will query Apple's servers as needed to check for notarization.) Note that if a ticket is stapled to the app, you can use Component > Show Notarization Ticket to see the Apple certificate that signed the ticket.
None detected The app or component does not appear to be notarized. This might be caused by an inability to connect to Apple's servers. However, a network connection is required only the first time that macOS checks for notarization of a given app, and then only if the notarization is not “stapled” to the downloaded copy. So even in the absence of Internet connectivity, it is likely the app is not actually notarized.
Not applicable The app or component is signed by Apple directly, and therefore is not required nor expected to be notarized. This typically applies to apps installed with macOS, downloaded from the Apple web site, or installed from the Mac App Store.
Conflicting signatures The app or component supports multiple processor architectures, which have different notarization statuses. See more below.
Verifying signature Apparency is still verifying the signature on the app or component, and can't evaluate the notarization status until this is complete.
Multiple values Multiple apps or components are selected in the browser, and these have different notarization statuses. Select a single component to see its notarization status.

What do the different Gatekeeper statuses mean?

In the info pane, the Gatekeeper status is described with one of the following:

Gatekeeper StatusDescription
Apple System The app or component was signed by Apple, and is always allowed to run. This applies to apps pre-installed with macOS and to some software downloaded from the Apple website — including most developer tools.
Mac App Store The app or component was signed by Apple for distribution via the Mac App Store, and is always allowed to run.
Notarized Developer ID The app or component was signed with an Apple-issued Developer ID certificate, and subsequently approved for distribution by Apple's notarization service. The code will be allowed to run by default, unless disabled via System Preferences, under Security & Privacy > General > Allow apps downloaded from (where “identified developers” refers to Developer ID certificates), or via system policy changes made through the spctl(8) tool.
Developer ID The app or component was signed with an Apple-issued Developer ID certificate, but does not appear to be notarized. However, macOS will allow this code to run, because (a) the developer began distributing apps under this Developer ID prior to the release of macOS 10.14.5 (April 8, 2019), and (b) the app or component has a verified signing time no later than June 1, 2019. [macOS 11 (Big Sur) and macOS 10.15 (Catalina) enforce both of these requirements on unnotarized code, while macOS 10.14 (Mojave) enforces only the first.]
Can't evaluate Apparency can't evaluate the Gatekeeper status because the signature itself is not valid, as shown by the Signed By identity (and documented below). Since the identity of the signing certificate can't be relied upon, it doesn't make sense to evaluate that identity against any Gatekeeper policy.
Not evaluated Apparency isn't able to evaluate the app or component against the Gatekeeper policies. Currently, this should only be the case for kernel extensions, which have special requirements that go beyond those for normal apps. (In particular, the Apple-issued Developer ID certificate must be explicitly approved for signing of kernel extensions, so an additional level of Apple review is involved.)
Rejected The app or component was signed with a certificate that is not trusted by Gatekeeper (or perhaps not even by macOS; see below). This might be case the if the component was signed with a third-party certificate (which would be uncommon) or perhaps with an Apple-issued certificate that is not of the Developer ID variety (such as an App Store distribution certificate, which is only supposed to be used for submission to Apple, but is sometimes mistakenly used elsewhere).
Unnotarized Developer ID The app or component was signed with an Apple-issued Developer ID certificate, but does not appear to be notarized. Since the exceptions described above for the Developer ID status are not met, macOS will not allow this code to run (unless it is found to be notarized when Gatekeeper runs).
Conflicting signatures The app or component supports multiple processor architectures, which have different Gatekeeper statuses. See more below.
Verifying signature Apparency is still verifying the signature on the app or component, and can't evaluate the Gatekeeper status until this is complete.
Multiple values Multiple apps or components are selected in the browser, and these have different Gatekeeper statuses. Select a single component to see its Gatekeeper status.

What do the different Signed By identities mean?

In the info pane, the Signed By identity will resemble one of the following:

Signed ByDescription
Software Signing The app or component was signed by Apple. This Apple certificate is used to sign the components of macOS itself (including those delivered through Software Update), as well as some software distributed through the Apple website, including most developer tools.
Apple Mac OS Application Signing The app or component was signed by Apple, prior to making it available on the Mac App Store. This applies to all apps from the store, whether made by Apple or by other developers. (All apps submitted to the Mac App Store are re-signed with this certificate before being made available for sale.)
Johnny Appleseed (123DE678IJ) The app or component was signed with the named certificate. The exact format varies with the type of certificate and the issuer. If it's an Apple-issued Developer ID certificate, there will usually be a parenthesized string of numbers and letters at the end, as in this example: this is the team identifier that Apple assigned to that developer's account. Click Show Code Signature to see details about the signing certificate.
No signature The app or component was not signed at all. This is often the case with older apps, or with developers who aren't particularly excited about paying Apple US$99 per year for the privilege of shipping software for macOS.
Ad-hoc signature The app or component was signed without using a certificate. This now-uncommon scheme allows certain code-signing features (such as entitlements) to be used with effectively unsigned code. But ad-hoc signatures don't tell you anything about the developer's identity.
Expired certificate The app or component was signed with a certificate that is now expired, and the signature doesn't have a verified signing time that predates the expiration. See more on macOS handling of expired certificates below.
Untrusted certificate The app or component was signed with a certificate that is not trusted by macOS. That is, the certificate was issued by a certificate authority that is not included in the macOS “system anchors.” This is unusual, especially since most modern apps are signed with certificates that were issued by Apple's own certificate authority (which is obviously trusted by macOS). See more on untrusted certificates and code-signing below.
Can't verify signature The app or component appears to have been corrupted or tampered with since being signed. As such, the identity implied by the signing certificate is not reliable. This could be a result of the app being compromised at the point of download. Or it could simply be the result of errors occurring during signing, or in a software update process — the latter is depressingly common, even and especially for built-in macOS apps. (For iOS apps installed on Apple Silicon Macs, read more below.)
Skipped verification due to size The app or component is so large that Apparency suspects it would take an unusually long time to verify, and so did not try to do so automatically: see more on this below.
Conflicting signatures The app or component supports multiple processor architectures, which were signed with different certificates. See more below.
Failed to read signature A low-level error occurred in the macOS security subsystem while attempting to read the signature. If this occurs, it probably indicates corruption of the app that fundamentally damaged the signature, and is unlikely to be recoverable.
Removed to DYLD shared cache The component is part of macOS itself, and the signature was removed when the Mach-O binary was moved into the DYLD shared cache — a macOS 11 (Big Sur) optimization.
Verifying signature Apparency is still verifying the signature on the app or component, and can't report the signing identity until this is complete.
Multiple values Multiple apps or components are selected in the browser, and these have different signing identities. Select a single component to see its signing identity.

What do the different Provisioned Entitlement statuses mean?

When viewing the entitlements with Component > Show Entitlements, you may see an additional entitlements view provisioning column header column. This appears only if the selected app has a provisioning profile, and shows the provisioned status of each entitlement. The meaning of each status icon is as follows:

Provisioned Entitlement StatusDescription
entitlement is provisioned The entitlement is one that requires provisioning, and is allowed by the provisioning profile. Such entitlements are usually for an Apple service — such as iCloud or push notifications — or for a macOS feature to which Apple has decided to restrict access, such as system extensions.
entitlement is not provisioned [required for this key] The entitlement is one that requires provisioning, but it is not allowed by the provisioning profile. As a result, macOS will likely prevent the app from opening. (The macOS kernel will intentionally crash the app when it finds that it is using entitlements that are not permitted by the provisioning.)
entitlement is not provisioned [not strictly required for this key] The entitlement is not allowed by the provisioning profile, but is one of a subset of entitlements that are only quasi-restricted by Apple. These include com.apple.security.application-groups (which allows the app to share “group containers” with other apps from the same developer) and com.apple.application-identifier (which is a meta-entitlement used to identify the app and developer). Because provisioning of these is not strictly enforced, there will likely be no adverse impact on the launching or operation of the app.
provisioning is not required for this key The entitlement does not require provisioning at all. Generally, the entitlements related to App Sandbox and runtime hardening fall into this category.

What does it mean when a code signature has a “verified signing time”?

All certificates — including Apple-issued Developer ID certificates — expire after some amount of time. (This is a security precaution, since the underlying technology and the attacks against it are always moving forward.) In the ideal case, developers replace certificates before they expire, and an app you download today will be signed with a still-valid certificate. But in the real world, developers don't always get ahead of expiring certificates — or you might just have an older version of an app and still want to use it after the certificate has expired.

However, an expired certificate does not necessarily make the code signature invalid. When an app is signed on macOS, the current date and time can be incorporated into the signature in a way that is independently verified by Apple. That is, instead of the app just claiming to have been signed at a specific date and time, the actual signing time is securely supplied by Apple, and bound to the code signature cryptographically. (This is known as a “trusted timestamp,” with an Apple server as the “Time Stamping Authority.”) This typically happens automatically when the developer signs the app, but it might have been disabled (see the codesign(1) man page, and the ‑‑timestamp option).

This becomes relevant when Apparency evaluates the trustworthiness of the code signature. If there is a verified signing time, macOS will evaluate the signing certificate as of that date and time. If the certificate is expired now, but was not expired (and was otherwise valid) at the time the app was signed, macOS might decide that the signature is still trusted. (There are exceptions; for example, a certificate might have been explicitly revoked, and might not be considered valid for any signature on any date.)

Even in the absence of a verified signing time, Gatekeeper is quite lax about expired certificates in code signatures. See more on this below.

Unfortunately, the way that this scenario is presented in the standard macOS certificate trust sheet is less than clear: if you examine the certificate details, you'll see that the certificate has expired, but macOS still says “this certificate is valid.” Of course, the certificate itself is no longer valid, but since it was valid at the verified signing time, the signature is nevertheless valid. However, macOS doesn't show the verified signing time anywhere, nor even note its existence.

Apparency attempts to improve matters by explicitly noting when a verified signing time is found in the code signature. When you use Component > Show Code Signature, if the code signature includes a verified signing time, it will be shown in the sheet: signature and trust dialog

If you click Show Certificate, you may still see the certificate-is-expired-but-valid confusion described above — since Apparency uses the standard macOS certificate trust sheet, and can't change this bit — but at least this gives some context to the confusion.

Why does Apparency complain that a certificate is expired when Gatekeeper doesn't seem to mind it?

If an app was signed with a certificate that has since expired — and the signature lacks a verified signing time — Apparency will show the Signed By identity as Expired certificate. However, macOS generally does not consider an expired certificate to invalidate a code signature, such as when evaluating Gatekeeper policies.

We can only speculate why this is the case. Presumably, too much would break if expired certificates invalidated a code signature, especially if it prevented otherwise-valid apps from being used. The existence of verified signing times ought to solve this problem, but in fact, these are not used consistently enough. Most third-party apps have them, but most Apple apps — and apps distributed via the App Store — do not.

In any case, Apparency shows expired certificates as such, so you can decide whether or not you care.

Why does Apparency say that a certificate is untrusted when codesign(1) doesn't complain?

If an app was signed with a certificate that is not trusted by macOS, Apparency will show the Signed By identity as Untrusted certificate. However, if you run codesign(1) with the ‑‑verify option, it might not report any error. That's because the macOS code-signing mechanism does not, by default, impose any trust requirements on the certificate used to sign an app. Features built on top of code-signing, such as Gatekeeper, can and do impose such trust requirements, but when you use codesign(1), you are interacting with the bare code-signing mechanism only.

To understand why this is the case, we have to go back in time. The macOS code-signing mechanism dates to Mac OS X 10.5 (Leopard), way back in 2007. In those early days, signed third-party apps were rare. Apple was code-signing components of macOS itself, but even those signatures were frequently broken by the Software Update process, with little ill effect. Indeed, before the introduction of Gatekeeper in Mac OS X 10.7 (Lion), Apple wasn't issuing code-signing certificates to third-party macOS developers. (Certificates issued to App Store developers, even with the advent of the Mac App Store, were never intended to be used for signing apps to be installed on macOS, but only for signing apps being submitted to App Review. App Store apps are always re-signed by Apple prior to being offered on the store.)

In those ancient times, a third-party developer could have gotten a signing certificate from some non-Apple certificate authority — any of the ones generally trusted via the macOS “system anchors” — but that would've been a lot of trouble and expense for no real benefit. In fact, the only benefit was that a code-signed app could be updated without losing access to any keychain items it created: as long as each new version of the app was signed with the same certificate as the original version of the app, it would maintain access. But even this could be achieved with a self-signed certificate, which can be created freely by a developer, and doesn't involve any third-party validation. It didn't matter that the self-signed certificate wasn't trusted by macOS; all that mattered is that the same self-signed certificate was used to sign subsequent app versions, indicating that they came from the same developer as the original.

Anyway, given that code signing was optional and uncommon for so many years after introduction, it is not so surprising that the basic code-signing mechanism doesn't enforce much actual policy — that's what features such as Gatekeeper added. As such, when you run codesign ‑‑verify, you are asking it to verify only two things:

Unless you've examined the designated requirement — such as by using codesign with the ‑‑display and ‑‑requirements options — you can't be certain that satisfies its Designated Requirement implies a trusted certificate. You can, however, ask codesign to check an additional, explicit requirement that includes trustworthiness. For example:

$ /usr/bin/codesign --verify --verbose=4 --test-requirement="=anchor trusted" /Applications/Some.app
/Applications/Some.app: valid on disk
/Applications/Some.app: satisfies its Designated Requirement
/Applications/Some.app: explicit requirement satisfied

Here, the explicit requirement says that the signing certificate must ultimately be issued by a certificate authority that is trusted by macOS. Often, this will be Apple's own certificate authority, but this requirement is more general than that. (Use anchor apple generic instead to require an Apple-issued certificate.)

Again, this is only interesting to understand what the codesign tool is actually checking — and what it isn't. It doesn't mean that macOS isn't checking the trust of code signing certificates in specific circumstances. For example, Gatekeeper rules are themselves code-signing requirements, just like the above. You can see these rules via something like:

/usr/sbin/spctl --list

In fact, these are the same requirements that Apparency uses to determine the Gatekeeper status.

Why would Apparency tell me an app was “downloaded” when it clearly wasn't?

When you download a file in your web browser, macOS records how and where it was downloaded. If the file is an app, this tells macOS to activate Gatekeeper when the app is first opened. (If the file contains an app, as in the case of a disk image or zip file, the download information gets copied along with the app. So even after you've dragged the app to your Applications folder, macOS still knows that the app was downloaded.) Usually, the result of Gatekeeper is an alert, saying that the app was “downloaded from the Internet,” and asking you if you still want to open it.

In between when you download a file, and when you click OK in that Gatekeeper alert, macOS considers the file to be in quarantine (this terminology was more whimsical before 2020). Once you've allowed Gatekeeper to open the app, it is no longer considered quarantined, but there may still be enough information left behind for Apparency to detect when it was downloaded and by what app (i.e. your web browser). Apparency shows this information in the info pane; you can click on the download date once to see the downloading app name, and a second time to see the kind of download (e.g. from the Internet).

This is all probably what you'd expect “downloaded” to mean. But macOS also applies the quarantine mechanism elsewhere. Most significantly, when an app uses the App Sandbox, all files saved by that app are considered quarantined. For example, say that you receive an email with a zip file attached, and that zip file contains an app. When you ask the Apple Mail app to save that attachment, the zip file gets quarantined: as a result, opening the zip file and then the app inside will activate Gatekeeper. This happens because Apple Mail uses the App Sandbox, and not because of any special knowledge about the source of the files being saved. (Contrast this with Safari or Chrome, which explicitly tell macOS to quarantine a downloaded file, because it came from the Internet.)

Of course, for an app like Apple Mail, almost every file it saves was essentially downloaded from the Internet. Other sandboxed apps might not be downloading anything, but the files they save will still be quarantined — for example, simply save an image in the Preview app and it will be quarantined. This is because macOS does not rely on the (sandboxed) app to decide if content is potentially unsafe, but instead quarantines pretty much everything, and leaves it to Gatekeeper to decide what should be checked and how. (Obviously, Gatekeeper is going to check a quarantined app, but even some kinds of documents can be unsafe and will be subject to Gatekeeper checks.)

So, if an app that you open with Apparency was quarantined — even if it wasn't strictly “downloaded” in the traditional sense — you might still see a Downloaded date in the info pane. Apparency can detect that the quarantine came from a sandboxed app, but it doesn't know whether there was any actual download involved. If you click on the date, Apparency will show the app that saved it, and if you click again, from App Sandbox (save or open).

Sometimes, simply opening a file, without ever changing or saving it, will cause a quarantine to be added.

When you use the standard File > Open dialog from a sandboxed app, macOS gives the app permission to open and/or save that file, depending on the app's entitlements. But, when the Resume feature of macOS saves the open windows of the app, it saves the app's permissions in a way that does not preclude changing the file, and this triggers a quarantine on the file. [More precisely, in a document-based app, AppKit creates a security-scoped bookmark for each open document URL, and if the URL is user-writable, it omits the NSURLBookmarkCreationSecurityScopeAllowOnlyReadAccess option — even if the app has declared its read-only intent via both the com.apple.security.files.user-selected.read-only=YES entitlement and the CFBundleTypeRole=Viewer document type declaration. This creation of a read-write bookmark triggers a quarantine on the file, at least in the absence of the com.apple.security.files.user-selected.executable=YES entitlement.]

This surprising behavior applies to Apparency itself: if you open a standalone executable with Apparency, you might find that Apparency claims that it was downloaded by Apparency itself! This is simply because Apparency opened it, even though it never changes or saves anything. This can be baffling, but it only happens when you open a standalone executable (not an app or other bundle); we don't try to fudge or hide it, because you should be able to trust that Apparency is showing you the actual quarantine information.

What are “code signing options” and how can I view them?

The macOS code signing mechanism has a number of additional options that can be applied to a component. These flags change the way that macOS handles certain aspects of the code signature when the app is used.

For example, there's a Library Validation option that restricts the app to using only those dynamic libraries or frameworks provided by macOS, or those signed by the same developer. And there is a Kill option that tells macOS that it should terminate the app if the code signature should become invalid while open.

To our knowledge, the only Apple documentation of these options are in the codesign(1) man page (see the Option Flags section), and in the Security/CSCommon.h header (see the SecCodeSignatureFlags enumeration). The latter contains some options not mentioned in the former.

Apparency doesn't show these options by default, because they are not terribly common, and (quite frankly) because we don't understand the nuances of them ourselves, and can't really provide any guidance on interpreting them! However, if you want to see them in Apparency, you can enable them using Apparency > Preferences > General > Show code signature options for selected component. With this enabled, Apparency will show the options at the bottom of the info pane. (Note that Apparency won't show the Runtime or Adhoc options here, though, since these are already represented elsewhere in the info pane — the first under Hardening and the second under Signed By.)

What is a “code signing identity” and what is it used for?

A code signing identity allows macOS to recognize a specific app from an Apple-registered developer, without regard to a particular version of that app. This is used by macOS to grant access to sensitive resources — such as keychain items or App Sandbox “containers” — in a way that won't break every time the app is updated.

In its typical form, a code signing identity consists of two pieces:

Any app that matches both of these attributes is assumed to be the “same” app, and is allowed to access the same resources. The developer can update the app with abandon, as long as the code signing identity doesn't change.

Usually, this all happens behind the scenes and isn't very interesting, but there are a few places where you do need to work with the code signing identity, such when creating a Privacy Preferences Policy Control (PPPC) configuration profile. You can grab the code signing identity from Apparency by selecting the app and choosing Edit > Copy Code Signing Identity (Cmd-Ctrl-C). The code signing identity can them be pasted into the profile's CodeRequirement key, for example.

A code signing identity — also known as a designated requirement — is defined using Apple's Code Signing Requirement Language. These requirements can get arbitrarily complex, and an app might not use the typical form. But for the curious, here's an annotated version of a typical code signing identity (the one for Apparency itself):
anchor apple generic /* signing certificate was issued by Apple, trusted by Apple Root CA */
   and identifier "com.mothersruin.Apparency" /* and app has this bundle identifier */
   and ( certificate leaf[field.1.2.840.113635.100.6.1.9] /* and signing certificate is the Mac App Store one */
         or ( certificate 1[field.1.2.840.113635.100.6.2.6] /* ... OR was issued by the Developer ID intermediate CA */
              and certificate leaf[field.1.2.840.113635.100.6.1.13] /* ... for Developer ID Application use */
              and certificate leaf[subject.OU] = "936EB786NH" ) ) /* ... for the developer with this team ID */

The team ID is an identifier that Apple assigns to each registered developer; every Developer ID certificate that Apple issues to that developer will have the same team ID, and so will meet the latter part of this requirement. (You'll see the same team ID in parentheses in the Signed By identity in Apparency's info pane.) This scheme avoids problems when the Developer ID certificate gets renewed between app updates.

The alternative check for the Mac App Store certificate allows the same resources to be shared between a Mac App Store version of the app, and the same app distributed outside the store; this is part of the default code signing identity, and doesn't necessarily mean that both versions actually exist.

Why does Apparency sometimes say that it skipped verification of the signature?

In order to verify the signature of an app or component, every file that makes up that component has to be read in its entirety, creating a cryptographic digest (or hash) of the complete component. This digest is then compared against the one that was produced when the component was signed by the developer. Any changes that are made to any file of the component are thus detected, because it will result in a different digest and invalidate the signature. (This is a bit of an oversimplification, but conceptually accurate anyway.)

In most cases, creating the digest takes a few seconds at most, and the signature is verified quickly. However, for extremely large apps, verification can start to take real time. For example, Xcode — weighing in at over 10 GB in size — can take several minutes to verify. (Anyone who has ever installed Xcode has surely noticed the long delay upon first launch!) You might want Apparency to do the verification anyway, if the signature is the information that you're interested in inspecting, but otherwise, it is just an annoying use of your CPU.

Apparency tries to guess when an app or component is so large that the verification will take an unusually long time. Where it believes this to be the case, Apparency will not automatically verify that component. Instead, it shows the Signed By identity as Skipped verification due to size. When this occurs:

  1. If you don't care about the signature of the component, you can ignore this entirely.
  2. If you would like to proceed with verification of the signature for just this single component, select it, click the Signature toolbar button Signature toolbar button (or use Cmd-Shift-S), and then choose Verify Signature.
  3. If you would to proceed with verification of the signatures for all components in this app, choose File > Verify All Signatures.
  4. If you would like Apparency to always verify all signatures, even where it believes that this make take a long time, go to Apparency > Preferences > General and uncheck Skip automatic signature verification for large code.

What does “In DYLD Shared Cache” mean?

The DYLD shared cache is an optimization that has been in use since Mac OS X 10.6 (Snow Leopard).

Most every app that runs on your Mac uses the standard system libraries and frameworks (such as AppKit), and those standard libraries in turn use hundreds more Apple-private libraries. Finding, loading and preparing every one of those libraries and frameworks can delay app startup significantly, resulting in lots of “bouncing” time in the Dock.

Instead, the work of finding and preparing all of those libraries is done once, and stored as the DYLD shared cache. When an app starts, it only needs to load the shared cache (along with any non-system frameworks it uses, of course). Moreover, since every other process is also loading that cache, the actual loading work (an mmap(2) call) happens only for the first process; the loaded cache is then simply vended to every subsequent process. This not only speeds up app launch time, but also decreases overall system memory usage, because every process is sharing the same copy of the system libraries (via virtual memory) rather than loading another copy.

Through macOS 10.15 (Catalina), the DYLD shared cache was rebuilt whenever new system libraries or frameworks were installed. That is, when Software Update installed new versions of any of the libraries in the cache, it would run the update_dyld_shared_cache(1) tool afterward.

However, in macOS 11 (Big Sur), Apple introduced the signed system volume, wherein the macOS system volume (made read-only in Catalina) becomes an Apple-signed snapshot that can't be modified at all — except by Software Update, which is essentially now installing an updated snapshot of the system.

With this new model, the libraries and frameworks in the DYLD shared cache are fixed precisely by the version of the system snapshot. This allows the work of building the shared cache to be moved from the installer to the building of macOS itself. That is, Apple delivers the DYLD shared cache as part of the signed system snapshot, and there's no need to run update_dyld_shared_cache on your Mac.

Which finally brings us back to what any of this has to do with Apparency! Because Apple is delivering the DYLD shared cache, they've decided that there is no longer any reason to deliver the actual libraries that went into that cache. From a user standpoint, they are indeed redundant. Unfortunately, from a development and debugging standpoint, this is quite painful, because it makes it much more difficult to analyze or otherwise reverse-engineer Apple's frameworks — which has become increasingly necessary as Apple's developer documentation has gotten progressively more useless.

Anyway, in Big Sur, if you examine a standard system framework, say AppKit.framework, you will find there is no actual Mach-O binary inside it (e.g. AppKit.framework/AppKit). Apparency can still open the framework, but the info pane will show the Executable as being simply In DYLD shared cache, instead of showing the usual processor architecture information. You can still use Component > Show Executable Information (Cmd-Shift-X), since Apparency retrieves the Mach-O binary information from the shared cache. This at least allows you to see the linked libraries and other parameters.

You will also notice that the code signature information is missing: Apparency shows the Signed By as Removed to DYLD shared cache. That's because the code signature normally lives inside the Mach-O binary (at least for frameworks and libraries), and that signature was removed in the process of building the DYLD shared cache. Essentially, the signature on the framework has been deleted — presumably, Apple is okay with this because the entire system snapshot is cryptographically signed, so the identity of the frameworks inside that snapshot is not in question.

If you look at the framework in the Finder or Terminal, you might notice there is still a _CodeSignature/CodeResources file, but this is a useless artifact of the former code signature. This file usually contains digests of the resource files provided by the framework — which of course still remain — but nothing will actually use this file, because the code directory that would normally reference it (by digest) is no longer present in the Mach-O binary.

In any case, the CodeResources files on the signed system volume are quite small, since they simply exempt all resources from the digest check — likely because this is redundant to the signing of the snapshot. Normally, the code-signing machinery would balk about such “custom omit rules,” but it has a special exemption for the system volume. (On the other hand, if you open a component from a different system volume, you're likely to get errors, because the exemption applies only to the booted system.)

What does “Conflicting signatures” mean? Why does Apparency show a processor architecture pop-up?

The macOS code signing mechanism stores most of the information about the signature inside the executable of the app or component. This information includes the entitlements and the code signing identity — along with a web of cryptographic digests (or hashes) that uniquely identifies the compiled code, the Info.plist and the other bundle resources (such as images or strings files).

If an app supports multiple processor architectures (e.g. Intel — 64-bit and Apple Silicon — 64-bit), there will actually be a separate code signature for each architecture. This is simply how the code signing mechanism is designed. (The app can even be “thinned” to remove architectures, without invalidating the signatures on the remaining architectures.) Typically, each of these distinct signatures is functionally identical: that is, signed by the same certificate, with the same entitlements, code signing identity, and so on. (They can't be exactly identical, however, because the compiled code is always going to differ.)

To ensure that a multiple-architecture component has functionally identical code signatures, Apparency will evaluate the signature for every architecture. If everything is indeed consistent, Apparency won't show anything special: the Signed By, Gatekeeper, Entitlements and other attributes will simply show the common values extracted from every architecture.

However, in the (unlikely!) event that Apparency does find a difference between signatures, it will instead show Conflicting signatures in the applicable field of the info pane. When you use Component > Show Code Signature or Component > Show Entitlements to get more details, you will be given a choice of architecture to examine. This allows you to see how the architectures differ. Obviously, the architecture that your Mac will use is the most interesting, but a difference in signatures is unusual enough that you may want to examine everything more closely.

Why does Apparency say it “Can't verify signature” for an iOS app installed on an Apple Silicon Mac?

On an Apple Silicon Mac, you can install previously-purchased iPhone or iPad apps from the App Store (from the Purchased area of the Account page). These get installed into the standard Applications folder, but of course are quite a bit different from a normal macOS app.

You can open one of these iOS apps using Apparency, but some things will look a bit odd. Most significantly, you'll see that under Signed By, Apparency shows Can't verify signature. If you use Component > Show Code Signature, you'll see that the verification failed because the “resource envelope is obsolete (custom omit rules).” This is because the rules applied to macOS apps (by the macOS code-signing machinery) don't quite make sense for the way that iOS apps are (re)signed by the iOS App Store.

As described above, part of verifying a code signature is verifying that the resources inside the app (such as strings or nib files) haven't been changed since the app was signed. For a standard macOS app, there are a handful of files that are allowed to change without being flagged as an error (for example, .DS_Store or PkgInfo files). In olden times, apps could add files to this list (i.e. “custom omit rules”), but since OS X 10.9 (Mavericks), such custom exclusions from the code signature have been prohibited. This is because macOS apps are not supposed to modify themselves — they should store customizations in standard places, usually inside a Library folder.

However, apps delivered from the iOS App Store are “customized” by the addition of SC_Info folders. These contain files related to the FairPlay DRM scheme, and are specific to the purchasing user. When Apple re-signs apps for delivery on the iOS App Store, it adds custom omit rules that exclude these SC_Info files. Presumably, on iOS devices, this allows the code signature to be verified properly. But on macOS, the very existence of those custom omit rules merely triggers an error, and verification of the (real) resource files is not even attempted.

We don't know what level of verification macOS does on these iOS apps, but whatever exemptions it makes seem to live outside the public code-signing APIs. So for the time being, at least, Apparency's evaluation of these apps doesn't make a lot of sense.