CAA tells certificate authorities which of them may issue for a name. A CA is required to check it at issuance and to refuse if it is not listed — which makes it the one control a domain owner has over the certificate ecosystem.
The three properties
| Property | Constrains |
|---|---|
issue | Who may issue any certificate for this name. |
issuewild | Who may issue a wildcard. If absent, issue governs wildcards too. |
iodef | Where a CA should report a request it refused. Rarely published and rarely acted on. |
Four live sets
0 issue "pki.goog"
0 issue "digicert.com" 0 issue "globalsign.com" 0 issue "letsencrypt.org" 0 issue "sectigo.com" 0 issuewild "digicert.com" 0 issuewild "letsencrypt.org" 0 issuewild "sectigo.com"
GitHub’s set is worth reading carefully. GlobalSign may issue an ordinary certificate and not a wildcard, because it appears under issue and not under issuewild. Publishing any issuewild overrides issue for wildcards entirely.
0 issue "letsencrypt.org" 0 issue "pki.goog" 0 iodef "mailto:dns-admin@wikimedia.org"
How a CA finds the record
Issuing for api.eu.example.com: 1. CAA at api.eu.example.com found? use it. stop. 2. CAA at eu.example.com found? use it. stop. 3. CAA at example.com found? use it. stop. 4. no record anywhere -> any CA may issue
It climbs until it finds a set, and the first set it finds is the whole answer. A record at a subdomain therefore replaces the apex policy for that name rather than adding to it — which is how a permissive subdomain record quietly undoes a strict apex one.
An empty issue value forbids everything
0 issue ";" means no authority may issue. It is the correct record for a name that should never have a certificate, and it is also what you accidentally publish if a provider interface treats an empty field as a valid value.