Saturday, May 7, 2022

Inside Code Signing Technotes

TN3125: Provisioning Profiles:

A macOS app can claim certain entitlements without them being authorized by a provisioning profile. These unrestricted entitlements include:



  • Those used to enable and configure the App Sandbox

  • Those used to configure the Hardened Runtime

In contrast, restricted entitlements must be authorized by a provisioning profile. This is an important security feature on macOS. For example, the fact that the keychain-access-groups entitlement must be authorized by a profile means that other developers can’t impersonate your app in order to steal its keychain items.


Modern systems no longer treat the profile’s property list as the source of truth. Rather, they use the binary form of the profile stored in the profile’s DER-Encoded-Profile property[…]

TN3126: Hashes:

Every now and again an issue crops up where you actually need to understand how code signing works. For example:

  • Using the Latest Code Signature Format has a diagnostic process that involves code signing hash slots. While that process is actionable in and of itself, it makes more sense if you know what those hash slots hold.

  • The issue covered by Updating Mac Software makes more sense once you understand code signing’s lazy per-page signature checking.

This technote explains how code signing uses hashes to protect the code’s executable pages, resources, and metadata from tampering. This technology is absolutely central to code signing’s core function: protecting code from malicious modification.

TN3127: Requirements:

However, in some cases requirements are important, especially on macOS. For example:

  • If you’re building an XPC service, you might want to restrict it to specific clients. The best way to do this is by setting a code signing requirement on the connection with xpc_connection_set_peer_code_signing_requirement. But what requirement to use?

  • When working with privacy-protected resources on macOS, like the microphone, you might find that the system fails to remember your choices during development.

  • You might find that the keychain presents unexpected authorization alerts when you deploy your app through a new channel, like TestFlight.


1 Comment RSS · Twitter

These look like pretty good documentation, but…

> Every now and again an issue crops up where you actually need to understand how code signing works.

"Every now and again"? Maybe go with "more often than not". The code signing, provisioning, entitlements, etc. workflow is complex to understand, and fraught with buggy, user-unfriendly tooling. Automatic provisioning added a while ago helps a lot, but still isn't good enough.

If Apple really thinks "every now and again" is a fair description, they have a dogfooding problem. Anecdotally, I can say:

1) the process is so annoying, it becomes a major factor in decision-making that ends with "screw it, we're just gonna make a web app". Apple needs to get out of their "but security!" mindset and figure out that their native tooling can never be worse than web tooling. It must always be at least as good, and better in some ways.

2) recently, a friend tried to play with using HomeKit in MacCatalyst. Configuring provisioning just right made them give up after a while. (Catalyst makes this extra-hard because you're provisioning for macOS and iOS, but App Store Connect doesn't really seem to be designed around this combination. Also, why Catalyst at all? Because HomeKit doesn't exist in AppKit.)

Again, good to see these tech notes. But we still need much better tooling.

Leave a Comment