CAA Records: Restrict Certificate Authorities for Your Domain

Every publicly trusted certificate authority can issue a certificate for your domain unless you say otherwise, and that default is risky when a misconfiguration or a supplier you don’t control requests a certificate on your behalf.
CAA (Certification Authority Authorization) records flip that default. You publish a simple policy in DNS that lists which CAs may issue for specific hostnames and how they should report attempts that don’t match your policy. Compliant CAs must honor the policy before they mint a certificate, which sharply reduces the chance of an unwanted certificate landing in logs or browsers.
Done carefully, CAA is low effort with high payoff. The trick is to roll it out in a way that doesn’t accidentally block your legitimate issuance paths—things like a CDN’s managed TLS, a WAF in front of your app, or a third-party platform that renews certificates for vanity domains. Below we explain how CAA works, what to publish, and how to test safely.
How CAA Records Work and Why They Matter
A CAA record is a DNS resource record with three parts: a flags byte, a tag, and a value. The tags you’ll use most are “issue” (authorize CAs for non-wildcard names), “issuewild” (authorize CAs for wildcard names, such as *.example.com), and “iodef” (tell CAs where to send incident reports). If there is no CAA record for a name or its ancestors, any CA may issue as long as it validates control. If there is at least one CAA record, a CA must be listed (or otherwise authorized by the set of records) before it can issue.
Flags are almost always 0. Setting the issuer-critical flag (value 128) tells CAs they must understand the tagged property or refuse issuance. In practice you keep this at 0 for the standard properties (“issue”, “issuewild”, “iodef”) and reserve it for extensions you’ve confirmed your chosen CA implements.
Inheritance, Alias Chasing, and the Search Algorithm
CAA is hierarchical. When a CA checks a name like www.app.example.com, it first performs a CAA query for that exact FQDN while chasing aliases (CNAME/DNAME). If the query returns a CAA RRset at that label (including at a CNAME target), that RRset is authoritative. If not, the CA walks up the original name’s parent chain (app.example.com → example.com → com) and stops at the first parent that has a CAA RRset. That means a single record at the apex can control issuance for the entire zone, while specific subdomains can override it where necessary.
Timing matters too. After a CA performs a successful CAA check for a name, it may rely on that result for up to the greater of the record’s TTL or 8 hours. After that window, it must re-check before issuing. A short TTL won’t force more frequent checks than 8 hours, but a long TTL (over 8 hours) can extend the reuse window; plan your change windows accordingly.
Allowlisting: the Core Policy
The safest pattern is to explicitly allow the CAs you use and nothing else. For example, if you rely on a single CA for all leaf certificates, publish an apex record such as: example.com. IN CAA 0 issue "digicert.com"
. If you also use a wildcard from a different CA, add example.com. IN CAA 0 issuewild "sectigo.com"
. If multiple providers legitimately issue for you (CDN, WAF, hoster), list them all—CAA authorization is a union: if any record authorizes a CA for a name, that CA may issue for that scope.
For parts of your namespace that should never receive public certificates (for example, internal-only names that still live in public DNS), you can deny issuance explicitly at that label with an empty issuer value that many administrators use: internal.example.com. IN CAA 0 issue ";"
. Place this only where you’re certain no automated system attempts a public certificate.
Reporting with IODEF
IODEF lets you receive notifications when a CA refuses issuance based on your policy. You can publish email and/or HTTPS endpoints, such as example.com. IN CAA 0 iodef "mailto:security@example.com"
and example.com. IN CAA 0 iodef "https://caa-reports.example.com/submit"
. Treat these as signals; not all CAs will send detailed reports, and the standard only requires attempting to notify.
Advanced Controls: Account and Method Binding
Extensions allow you to narrow issuance further, which helps against domain-control verification bypasses. The accounturi
parameter binds issuance to a specific CA account (often your ACME account URL). The validationmethods
parameter restricts which DCV methods a CA can use (for example, permitting only DNS-01, and not HTTP-01 or TLS-ALPN-01). A record might look like: example.com. IN CAA 0 issue "letsencrypt.org;accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/123456;validationmethods=dns-01"
. Only rely on these if your chosen CA implements them; otherwise, treat them as advisory. Don’t mark them critical unless you’ve confirmed support, or you could block legitimate renewals.
Deployment without Breaking Existing Issuance
Map your issuance paths first. Inventory every place certificates come from today: your primary CA, CDNs, WAFs, managed platforms, and any automated ACME clients. Vendors sometimes switch underlying CAs, so prefer authorizing the CA they actually use (the issuer domain they publish), not the platform brand, unless documentation says otherwise.
Start permissive, then tighten. At the apex, add “issue” for your known CA(s) and an iodef contact. Wait through at least one renewal or a staging run and verify nothing breaks. If you also use wildcards, add “issuewild” entries for those CAs. Once renewals and new orders succeed under the new policy, remove unused authorizations and add explicit denies at labels that should never get a certificate.
Mind aliases. Because CAA queries chase CNAMEs, a CAA RRset at the CNAME target applies to your name. However, the parent-walk is on your original domain’s parents, not the target’s. Avoid alias loops and be careful when pointing at third-party targets that publish their own CAA at the target label, since that policy can effectively control issuance for your name.
Choose practical TTLs. Since the reuse window is the greater of the TTL and 8 hours, TTL values below 8 hours won’t cause CAs to re-check more often than every 8 hours. Use modest TTLs (for example, 4–24 hours) so changes propagate reasonably fast via DNS caches without expanding the reuse window excessively.
How to Test CAA Safely
Check the DNS data you intend to publish before you hit “Save.” Use a local resolver and at least one public resolver to confirm you see the same answers. Query the exact FQDNs you issue for and their parents, and test both A/AAAA reachability and CAA visibility if your validation depends on method binding.
If you rely on an automated issuance system, run a staging issuance or a dry run after publishing CAA. Many ACME clients can point at a CA’s staging directory; a successful authorization followed by issuance is a strong signal that your policy is compatible.
Validate from multiple networks. Some failures only appear when a CA’s validators hit a different anycast site, or when IPv6 pathing diverges. Spot-checking from dual-stack vantage points reduces surprises and catches firewall rules that might interfere with DCV.
Examples You Can Adapt
Minimal allowlist for one CA: example.com. IN CAA 0 issue "digicert.com"
and example.com. IN CAA 0 iodef "mailto:security@example.com"
(authorizes only DigiCert for non-wildcards, sends email on policy hits).
Separate CA for wildcards: example.com. IN CAA 0 issue "letsencrypt.org"
and example.com. IN CAA 0 issuewild "sectigo.com"
(Let’s Encrypt issues leaf SANs; Sectigo issues *.example.com).
Deny issuance for a sub-tree that should never have public certs: internal.example.com. IN CAA 0 issue ";"
(publish this only on labels where you are certain no automated process requests a public certificate).
Bind issuance to your ACME account and method: example.com. IN CAA 0 issue "letsencrypt.org;accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/123456;validationmethods=dns-01"
(allows issuance only from your specific ACME account, using DNS-01).
Common Pitfalls and How to Avoid Them
Forgetting a provider: if your CDN or WAF terminates TLS, it probably issues on your behalf; add its CA to your allowlist. Misusing the critical flag: enabling it on properties your CA doesn’t implement could block issuance; keep it at 0 unless you’ve confirmed support. Publishing only at a subdomain when you intend to cover the zone: remember that CAA climbs from the requested name to the first parent with a CAA RRset, so put policy at the apex unless you’re intentionally scoping it narrowly.
Finally, monitor. Watch certificate transparency logs for your domains and review CAA reports you receive via iodef. When vendors change back-end CAs, update your allowlist promptly and plan a short overlap where both old and new are authorized to avoid renewal gaps.