Operations

CAA records explained: RFC 8659, accounturi, validationmethods

By · Last verified

A CAA (Certification Authority Authorization) record is a DNS record that tells certificate authorities which of them may issue for your domain. Every publicly trusted CA must check CAA before issuing a TLS certificate and must refuse if the record does not authorize it. RFC 8659 is the current specification, and RFC 8657 adds ACME account and validation-method restrictions.

What CAA does and does not do

CAA is a control that CAs enforce on themselves at issuance time. It reduces the number of CAs whose validation bugs or social engineering could produce a certificate for your name from "every trusted CA" to the few you list.

CAA has clear limits:

  • Browsers ignore it. A browser never checks CAA, so a mis-issued certificate from a CA that ignored your record is still accepted until it is revoked. For detection, monitor Certificate Transparency.
  • It applies only at issuance. Existing certificates are unaffected when you add or change a record.
  • It is not authentication. CAA restricts which CA may issue; the CA still has to validate that the requester controls the domain through domain control validation.

CAA checking became mandatory on September 8, 2017 through CA/Browser Forum Ballot 187. The Baseline Requirements now require it for every name in a TLS certificate, and since Ballot SC-067 the lookup must also be corroborated from multiple network perspectives.

Record format

Every CAA record has three parts: a flags byte, a tag, and a value.

example.com.  3600  IN  CAA  0 issue "letsencrypt.org"
;                             | |     |
;                         flags tag   value: CA domain [; parameters]
Tag Purpose Defined in
issue Authorizes a CA to issue any certificate for this name, including wildcards unless issuewild is present RFC 8659
issuewild Authorizes a CA to issue wildcard certificates; when present it replaces issue for wildcards RFC 8659
iodef Where a CA may report a refused request, as mailto: or https: URL RFC 8659
issuemail Authorizes a CA to issue S/MIME certificates for email addresses at this domain RFC 9495

The flags value is almost always 0. Setting 128 marks the record critical: a CA that does not understand the tag must refuse to issue. Use it only when an unknown tag really must block issuance.

An empty CA domain forbids issuance. 0 issue ";" means no CA may issue for the name, which is useful for domains that should never have certificates, such as parked domains or mail-only subdomains.

How CAs find the relevant record set

A CA looks for CAA records starting at the exact name in the certificate and climbs toward the root, stopping at the first name that has any CAA records. This is called tree climbing:

Request for: shop.eu.example.com
  1. shop.eu.example.com   CAA?  none
  2. eu.example.com        CAA?  none
  3. example.com           CAA?  0 issue "letsencrypt.org"   <- relevant record set, stop
  (com and the root are not consulted once a record is found)

Three consequences follow. First, one record at the registered domain covers all subdomains. Second, a record on a subdomain completely overrides the parent; the sets are not merged. Third, CAA lookups follow CNAMEs like any DNS query, so if blog.example.com is a CNAME to a hosting provider, the provider's CAA records apply to that name.

For wildcards the climb starts at the base name: for *.example.com the CA looks at example.com.

issue versus issuewild

The issuewild tag exists so that you can allow ordinary certificates more widely than wildcards, or the opposite. The decision is easy to get wrong, so here is how a CA decides:

Records at the relevant name Non-wildcard request Wildcard request
issue "ca-a.example" only ca-a may issue ca-a may issue
issue "ca-a.example" + issuewild "ca-b.example" ca-a only ca-b only
issue "ca-a.example" + issuewild ";" ca-a may issue nobody
issuewild "ca-b.example" only any CA ca-b only
issue ";" only nobody nobody

Multiple records with the same tag are additive. Two issue records for two CAs authorize both.

accounturi and validationmethods

RFC 8657 lets you narrow an authorization from "this CA" to "this account at this CA, using these methods". Both parameters follow the CA domain, separated by semicolons, and both are supported by Let's Encrypt.

; Only my Let's Encrypt account may issue, and only via dns-01
example.com. IN CAA 0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890; validationmethods=dns-01"
  • accounturi binds issuance to one ACME account URL. Someone who temporarily hijacks your web server or DNS but does not hold your ACME account key cannot obtain a certificate. Let's Encrypt account URIs look like https://acme-v02.api.letsencrypt.org/acme/acct/ followed by the numeric account ID; your ACME client shows it after registration.
  • validationmethods limits the challenge types the CA may use. Valid values for ACME are the challenge names: http-01, dns-01 and tls-alpn-01. Restricting to dns-01 blocks an attacker who controls only your web server.

These parameters are powerful and easy to break. Staging and production use different account URLs, a server rebuild may register a new account, and several teams may use separate accounts. Add one issue record per legitimate account rather than replacing the only one. See the ACME protocol for how accounts and challenges work.

CA identifiers

The value in an issue record is the CA's own identifying domain, not the brand you bought from. Resellers sell certificates from a handful of issuing CAs, so check the issuing CA's documentation or the Issuer of an existing certificate. ACME CAs also publish the value as caaIdentities in their directory.

CA CAA value
Let's Encrypt letsencrypt.org
Google Trust Services pki.goog
DigiCert digicert.com
Sectigo sectigo.com
GlobalSign globalsign.com
SSL.com ssl.com
Amazon amazon.com

Some CAs accept several identifiers for historical brands, and ZeroSSL certificates are issued under Sectigo. When in doubt, confirm with the CA before adding a restrictive record.

Example zone and lookup

A typical configuration authorizes one primary CA, a backup CA, and reporting. In a BIND-style zone file:

$ORIGIN example.com.
@        3600 IN CAA 0 issue "letsencrypt.org"
@        3600 IN CAA 0 issue "pki.goog"
@        3600 IN CAA 0 issuewild "letsencrypt.org"
@        3600 IN CAA 0 iodef "mailto:security@example.com"
; api is hosted on a cloud platform whose certificates come from Amazon
api      3600 IN CAA 0 issue "amazon.com"
; this name must never have a certificate
legacy   3600 IN CAA 0 issue ";"

Query the records with dig:

dig +short CAA example.com
0 issue "letsencrypt.org"
0 issue "pki.goog"
0 issuewild "letsencrypt.org"
0 iodef "mailto:security@example.com"

For api.example.com the CA stops at the record set on api itself and never consults example.com. To see what a CA will actually use for a given name, walk up the labels yourself or use the CAA checker, which performs the same climb. The CAA generator builds records with correct quoting for common DNS providers.

Keeping a backup CA in the record is a practical choice: if your main CA has an outage or a policy change, you can switch without waiting for a DNS change to propagate.

DNS errors and DNSSEC

A CAA lookup that fails is not the same as a lookup that returns no records. If the authoritative server returns SERVFAIL, times out, or answers CAA queries with NOTIMP, the CA cannot tell whether a forbidding record exists and will usually refuse. The Baseline Requirements allow a CA to treat a lookup failure as permission only if the failure is outside its infrastructure, it retried at least once, and the zone has no DNSSEC validation chain to the root.

Let's Encrypt's documentation lists the usual culprits:

  • DNSSEC signing bugs that only appear for empty responses, which CAA answers often are.
  • Name servers that return NOTIMP for unknown query types instead of an empty NOERROR answer, which violates RFC 1035.
  • Firewalls in front of name servers that drop queries for unfamiliar record types.

Your DNS provider does not need a CAA editor to be compatible; it only has to answer CAA queries correctly with an empty response.

CAA rechecks and timing

CAs check CAA close to the moment of issuance, not only when validating the domain. The Baseline Requirements require a CA to issue within 8 hours of its CAA check, or within the record's TTL if that is longer, which is why Let's Encrypt limits authorization reuse to 7 hours in its tlsserver and shortlived profiles to avoid separate rechecks. Practically, a CAA change takes effect at your next order once DNS caches expire, so lower the TTL before a migration.

Rolling out CAA safely

The safe way to introduce CAA is to inventory first and restrict second. A record that forgets one legitimate issuer breaks that issuer's next renewal, often weeks later, when nobody remembers the DNS change.

  1. Inventory. Search Certificate Transparency logs for every certificate issued for your domain and its subdomains in the past year, for example with CT search. Note each issuing CA, including those used by CDNs, email providers, status pages and other SaaS tools.
  2. Publish a permissive record. List every CA you found with issue, and add iodef so that CAs that support reporting can tell you about refused requests.
  3. Override where needed. Give subdomains hosted by third parties their own CAA set instead of widening the parent.
  4. Tighten gradually. Add issuewild, accounturi or validationmethods one step at a time, and trigger a renewal on staging after each change.
  5. Re-check periodically. New vendors arrive; repeat the CT inventory every quarter.

Common mistakes

Most CAA failures come from forgetting that the record applies to every subdomain and every certificate source. Review this list before publishing a restrictive record:

Mistake Effect Fix
Listing the reseller's brand instead of the issuing CA Commercial order fails at issuance Use the issuing CA's identifier
Forgetting a CDN or SaaS that issues certificates for a subdomain That platform's renewal fails Add its CA, or a CAA set on that subdomain
issuewild added without wildcard plans Wildcard renewals blocked Remove it or list the right CA
accounturi with only the staging or old account Production renewal fails Add a record per account
Typo in quotes or semicolons Record ignored or rejected by the panel Generate with a tool and verify with dig

When an issuance fails because of CAA, the ACME error type is caa and the message names the domain; CAA record prevents issuance walks through the fix.

FAQ

Do I need a CAA record?

No. Without CAA records any publicly trusted CA may issue for your domain once it validates control. A CAA record is an optional safety net that limits the damage if an attacker can pass domain validation at some other CA, or if another team buys a certificate from a CA you do not approve.

Does CAA affect certificates that are already issued?

No. CAs check CAA only at issuance time, and browsers never look at CAA. Adding a restrictive record does not invalidate existing certificates, but the next renewal from a CA that is not listed will fail.

What value do I use for Let's Encrypt?

Use 0 issue "letsencrypt.org". Add 0 issuewild "letsencrypt.org" only if you want wildcard rules that differ from non-wildcard rules. The value is also published as caaIdentities in the ACME directory of every ACME CA.

Will a CAA record on example.com block a subdomain hosted elsewhere?

Yes, unless the subdomain has its own CAA records. The CA climbs from the requested name toward the root and uses the first CAA record set it finds, so put a record on the subdomain that lists the other provider's CA. If the subdomain is a CNAME, the CAA records at the CNAME target apply.

Sources

  1. RFC 8659: DNS Certification Authority Authorization (CAA) Resource Record
  2. RFC 8657: CAA extensions for account URI and ACME method binding
  3. RFC 9495: CAA processing for email addresses
  4. CA/Browser Forum Ballot 187: Make CAA checking mandatory
  5. CA/Browser Forum Baseline Requirements
  6. Let's Encrypt: Certification Authority Authorization (CAA)