A Primer on Gatekeeper¶
Gatekeeper is the name Apple gives to a set of technologies that enforce application execution policies at the operating system level. Essentially, Gatekeeper answers the question is this software allowed to run.
When Gatekeeper runs, it performs a security assessment against the
binary and the currently configured system policies from the system policy
database (see man syspolicyd
). If the binary fails to meet the requirements,
Gatekeeper prevents the binary from running.
The spctl
Tool¶
The spctl
program distributed with macOS allows you to query and
manipulate the assessment policies.
If you run sudo spctl --list
, it will print a list of rules. e.g.:
$ sudo spctl --list
8[Apple System] P20 allow lsopen
anchor apple
3[Apple System] P20 allow execute
anchor apple
2[Apple Installer] P20 allow install
anchor apple generic and certificate 1[subject.CN] = "Apple Software Update Certification Authority"
17[Testflight] P10 allow execute
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.1] exists and certificate leaf[field.1.2.840.113635.100.6.1.25.1] exists
10[Mac App Store] P10 allow install
anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.10] exists
5[Mac App Store] P10 allow install
anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.10] exists
4[Mac App Store] P10 allow execute
anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] exists
16[Notarized Developer ID] P5 allow lsopen
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and notarized
12[Notarized Developer ID] P5 allow install
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13]) and notarized
11[Notarized Developer ID] P5 allow execute
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and notarized
9[Developer ID] P4 allow lsopen
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and legacy
7[Developer ID] P4 allow install
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13]) and legacy
6[Developer ID] P4 allow execute
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and (certificate leaf[timestamp.1.2.840.113635.100.6.1.33] absent or certificate leaf[timestamp.1.2.840.113635.100.6.1.33] < timestamp "20190408000000Z")
2718[GKE] P0 allow lsopen [(gke)]
cdhash H"975d9247503b596784dd8a9665fd3ff43eb7722f"
2717[GKE] P0 allow execute [(gke)]
cdhash H"cf782d6467be86b73a83d86cd6d8c9f87d9d9ce5"
...
18[GKE] P0 allow lsopen [(gke)]
cdhash H"cf5f88b3b2ff4d8612aabb915f6d1f712e16b6f2"
15[Unnotarized Developer ID] P0 deny lsopen
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists
14[Unnotarized Developer ID] P0 deny install
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13])
13[Unnotarized Developer ID] P0 deny execute
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and (certificate leaf[timestamp.1.2.840.113635.100.6.1.33] exists and certificate leaf[timestamp.1.2.840.113635.100.6.1.33] >= timestamp "20190408000000Z")
```
The first line of each item identifies the policy. The second line is a
code requirement language expression. This is a DSL that compiles to a
binary expression tree for representing a test to perform against a binary.
See man csreq
for more.
Some of these expressions are pretty straightforward. For example,
the following entry says to allow executing a binary with a code signature
whose code directory hash is cf782d6467be86b73a83d86cd6d8c9f87d9d9ce5
:
2717[GKE] P0 allow execute [(gke)]
cdhash H"cf782d6467be86b73a83d86cd6d8c9f87d9d9ce5"
The code directory refers to a data structure within the code
signature that contains (among other things) content digests of the binary. The
hash/digest of the code directory itself is effectively a chained digest to the
actual binary content and theoretically a unique way of identifying a binary. So
cdhash H"cf782d6467be86b73a83d86cd6d8c9f87d9d9ce5"
is a very convoluted
way of saying allow this specific binary (specified by its content hash)
to execute.
Other rules are more interesting. For example:
11[Notarized Developer ID] P5 allow execute
anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists
and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and notarized
We see the description (Notarized Developer ID
) but what does that
expression mean?
Well, first this expression parses into a tree. We won’t attempt to format
the tree here. But essentially the following conditions must all
be true:
anchor apple generic
certificate 1[field.1.2.840.113635.100.6.2.6] exists
certificate leaf[field.1.2.840.113635.100.6.1.13] exists
notarized
anchor apple generic
and notarized
are essentially special expressions
that expand to mean the certificate signing chain leads back to an Apple
root certificate authority (CA) and there is a supplemental code signature
from Apple that can only come from Apple’s notarization service.
But what about those certificate
expressions? That
certificate <position>[field.*]
syntax essentially says the code signature
certificate at ``<position>`` in the certificate chain has an X.509 certificate
extension with OID ``X`` (where X
is a value like A.B.C.D.E.F
).
This is all pretty low level. But essentially X.509 certificates can have a series of extensions that further describe the certificate. Apple code signing uses these extensions to convey metadata about the certificate. And since code signing certificates are signed, whoever signed those certificates is effectively also approving of whatever is conveyed by the extensions within.
But what do these extensions actually mean? Running rcodesign x509-oids
may give us some help:
$ rcodesign x509-oids`
...
Code Signing Certificate Extension OIDs
...
1.2.840.113635.100.6.1.13 DeveloperIdApplication
...
Certificate Authority Certificate Extension OIDs
...
1.2.840.113635.100.6.2.6 DeveloperId
We see 1.2.840.113635.100.6.2.6
is the OID of an extension on
certificate authorities indicating they act as the Apple Developer
ID certificate authority. We also see that 1.2.840.113635.100.6.1.13
is the OID of an extension saying the certificate acts as a code signing
certificate for applications associated with an Apple Developer ID.
So, what this expression translates to is essentially:
Trust code signatures whose certificate signing chain leads back to an Apple CA.
The signer of the code signing certificate must have the extension that identifies it as the Apple Developer ID certificate authority.
The code signing certificate itself must have the extension that says it is an Apple Developer ID for use with application signing.
The binary is notarized.
In simple terms, this is saying allow execution of binaries that were signed by a Developer ID code signing certificate which was signed by Apple’s Developer ID certificate authority and are also notarized.