CAA Records
CAA records
CAA stands for Certification Authority Authorization. The record tells the world which Certificate Authorities are allowed to issue certificates for a domain. Before any public CA issues a cert, it is required by the CA/Browser Forum baseline requirements to check the target domain’s CAA record. If the requesting CA isn’t listed, issuance fails.
CAA is not protection against a compromised key or a compromised CA. It’s protection against the wrong CA — one that shouldn’t be able to issue for your domain — being tricked into doing so anyway. That attack pattern is real and well-documented.
What a CAA record looks like
A typical CAA set for a domain that uses Let’s Encrypt for everything:
dig isidoregroup.com CAA
;; ANSWER SECTION:
isidoregroup.com. 3600 IN CAA 0 issue "letsencrypt.org"
Three fields after CAA:
- Flags (
0). The only meaningful flag is the critical bit (128). Set to0for normal records,128for “if you don’t understand this record, refuse to issue.” Almost everyone uses0. - Tag (
issue). The three common tags:
–issue— names a CA permitted to issue any certificate type.
–issuewild— names a CA permitted to issue wildcard certificates specifically.
–iodef— an incident-report URL (mailto:orhttps:) that CAs can use to notify you of failed issuance attempts. - Value (
"letsencrypt.org"). The CA’s identifier, in quotes. Different CAs publish their own identifier strings:digicert.com,sectigo.com,globalsign.com, etc.
You can list multiple CAs by publishing multiple CAA records:
isidoregroup.com. 3600 IN CAA 0 issue "letsencrypt.org"
isidoregroup.com. 3600 IN CAA 0 issue "digicert.com"
Both Let’s Encrypt and DigiCert can issue. Any other CA must refuse.
To restrict wildcards specifically — useful when you want only one CA to be allowed to issue *.isidoregroup.com certificates — combine issue and issuewild:
isidoregroup.com. 3600 IN CAA 0 issue "letsencrypt.org"
isidoregroup.com. 3600 IN CAA 0 issuewild "digicert.com"
Any CA on the issue list can issue regular certs. Only DigiCert can issue wildcards.
To deny all CAs entirely (rare, but valid for domains that should never have public certs):
isidoregroup.com. 3600 IN CAA 0 issue ";"
The semicolon means “no CA permitted.”
What Cathedra checks
DnsHygieneCheck calls dns_get_record($domain, DNS_CAA). The behavior is deliberately gentle.
When no CAA records exist:
status: info / severity: null
“No CAA records found. Any CA can issue certificates for this domain.”
Recommendation: “Consider adding CAA records to restrict certificate issuance to your preferred CA(s).”
Note: info, not warning. Missing CAA is not a security failure. The web was running fine without CAA for decades. Cathedra surfaces it as a hardening opportunity, not a defect. On the audit report, this is the line you’d recommend to a security-conscious client during quarterly review — not something you call them at midnight about.
When CAA records exist, Cathedra extracts the issue tag values and returns:
status: pass
“{N} CAA record(s) found. Permitted issuers: {comma-separated CA list}”
If CAA records exist but only with iodef (no issue or issuewild), Cathedra still returns pass — the record set is present — but the permitted-issuers list will read (wildcard), meaning “no explicit issuer restrictions configured.”
When CAA is worth adding
CAA earns its keep on three categories of domain:
- Domains running their own internal CA. If a client uses an internal PKI and never wants a public CA to issue certs for an internal hostname, CAA can lock that down at the DNS level.
- High-value domains where credential theft is a real concern. If an attacker steals a domain admin’s password at a CA we don’t use, CAA blocks the attacker from getting a working cert.
- Domains where we know the cert issuance pattern is stable. If a client only ever uses Let’s Encrypt and DigiCert and that’s not changing, lock it down. The cost of CAA is “you have to remember to update the record before adding a new CA.”
CAA is not worth adding when:
– The client uses many CAs across many services and doesn’t know which.
– Cert issuance is automated by a vendor whose CA changes are out of your hands.
– The client doesn’t yet have stable processes around DNS changes (a forgotten CAA update can break a renewal months later).
A practical pitfall
When a client updates from Let’s Encrypt to a different CA — say, switching to a paid DV cert from Sectigo — and the renewal silently fails, CAA is one of the first three things to check. The cert issuance log at the CA will say CAA prohibits issuance or similar. The fix is one DNS record: add 0 issue "sectigo.com" to the CAA set, wait for TTL, retry the issuance.
Cheat sheet
| Condition | Cathedra status | Notes |
|---|---|---|
| No CAA records | info | Hardening opportunity, not a failure |
CAA records present, with issue tags |
pass | Lists permitted CAs in the finding |
CAA records present, no issue tag |
pass | Permitted-issuer list reads (wildcard) |
What you should remember
- CAA tells public CAs which of them may issue certs for the domain. Other CAs must refuse.
- Cathedra returns
info— not warning — when CAA is missing. This is intentional. Surface it as a hardening recommendation, not an urgent finding. - When CAA is present, the pass message lists the permitted issuers: “{N} CAA record(s) found. Permitted issuers: {list}”
- Use
issuefor any cert type,issuewildfor wildcards specifically,iodeffor incident-report notification. - Adding CAA without a plan for CA changes can break renewals later. Document it in IT Glue when you do.
Next lesson: DNSSEC — why most domains skip it, and how Cathedra detects it.
Cathedra alignment: DnsHygieneCheck — CAA Records
