Public TLS certificates depend on domain validation and the domain owner's issuance policy. CAA records publish that policy in DNS, and dig reveals which certificate authorities a domain permits before a certificate order or provider change.

The issue tag permits a certificate authority to issue ordinary certificates. It also applies to wildcard certificates unless issuewild records specify a separate wildcard policy. The iodef tag supplies an incident-reporting destination rather than permission to issue.

A hostname can inherit its policy from a parent domain. Certificate authorities follow aliases during each CAA query and search successive parents of the original name until the first non-empty CAA record set; records higher up are not combined with that set. A lookup shows current policy, not existing certificates or a guarantee that an order will succeed.

dig must already be installed; How to install dig on Ubuntu or Debian covers Ubuntu and Debian. The public DNS queries below use Cloudflare's resolver at 1.1.1.1 and disclose the queried names to it; private names require an appropriate internal resolver.
Related: How to query DNS records with dig
Related: How to compare DNS answers across resolvers with dig
Tool: CAA Validation Report

Steps to check CAA records with dig:

  1. Query the CAA records for the certificate hostname.
    $ dig @1.1.1.1 www.cloudflare.com CAA +noall +comments +answer
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19632
    ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
    
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 1232

    The public hostname www.cloudflare.com has NOERROR with ANSWER: 0, so there are no CAA records at this name in this response. For your own certificate, replace it with the exact hostname; for a wildcard such as *.cloudflare.com, query cloudflare.com without the asterisk. +noall clears the display options, then +comments and +answer restore the status and answer records.

    SERVFAIL or a timeout is a failed lookup, not an empty policy; NXDOMAIN means the queried name does not exist. If the answer contains CNAME records, the recursive resolver normally follows them for CAA. A response containing only aliases needs a CAA query for the last target before concluding that the CAA set is empty.

  2. Query the parent domain when the hostname has no CAA records.
    $ dig @1.1.1.1 cloudflare.com CAA +noall +comments +answer
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41175
    ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 11, AUTHORITY: 0, ADDITIONAL: 1
    
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 1232
    ;; ANSWER SECTION:
    cloudflare.com.		300	IN	CAA	0 iodef "mailto:tls-abuse@cloudflare.com"
    cloudflare.com.		300	IN	CAA	0 issue "comodoca.com"
    cloudflare.com.		300	IN	CAA	0 issue "digicert.com; cansignhttpexchanges=yes"
    cloudflare.com.		300	IN	CAA	0 issue "letsencrypt.org"
    cloudflare.com.		300	IN	CAA	0 issue "pki.goog; cansignhttpexchanges=yes"
    cloudflare.com.		300	IN	CAA	0 issue "ssl.com"
    cloudflare.com.		300	IN	CAA	0 issuewild "comodoca.com"
    cloudflare.com.		300	IN	CAA	0 issuewild "digicert.com; cansignhttpexchanges=yes"
    cloudflare.com.		300	IN	CAA	0 issuewild "letsencrypt.org"
    cloudflare.com.		300	IN	CAA	0 issuewild "pki.goog; cansignhttpexchanges=yes"
    cloudflare.com.		300	IN	CAA	0 issuewild "ssl.com"

    The first CAA set is at cloudflare.com, so these 11 records apply to www.cloudflare.com. If another name's parent is also empty, the search continues one label at a time toward, but not including, the DNS root. After an empty alias lookup, the next parent is from the original queried name, not the alias target. Successful empty responses at every level mean CAA imposes no issuance restriction.

    After CAA, each row contains flags, a tag, and a quoted value. The issue row beginning with digicert.com lists DigiCert's issuer identifier; text after the semicolon contains issuer parameters. When issue records restrict ordinary certificates, an intended CA absent from all of them is not authorized. For a wildcard, issuewild rows take precedence when present. An empty issuer such as issue ";" authorizes nobody, but does not cancel another valid authorization in the same set.

    These records all have flags 0. A flags value with bit 128 set makes its property critical; an unsupported critical tag prevents issuance even beside a matching issuer. Parameters can also constrain issuance, so CA documentation governs their interpretation. A set containing only iodef does not restrict issuance. RFC 8659 defines the lookup and authorization rules; DNS data, record order, and TTLs can change.

Share this guide