UnveilTech

UnveilScan Blog

← All articles

Try UnveilScan free

CAA records: who can issue certs for your domain

Posted 2026-04-29 · 5 min read · DNSPKI

A Certification Authority Authorization record is two lines of DNS that tell the world's Certificate Authorities: "only these CAs are allowed to issue certs for my domain. If a request comes in to anyone else, refuse it." Per RFC 8659 (CAB Forum baseline mandatory since September 2017), every CA MUST check CAA before issuing.

Five minutes to deploy, near-zero maintenance, real protection against rogue cert issuance. Yet only ~30% of domains we scan have one. Let's fix that.

The threat without CAA

A CA's job is to verify domain control before issuing a cert. Verification is usually a DNS challenge or HTTP-01 challenge. Both are robust under normal circumstances, but they fail under three scenarios:

In all three cases, an attacker can mint a valid cert for your domain from any compliant CA worldwide. CAA limits this to ONE CA — the one you actually use. Attacks now require compromising YOUR specific CA, which dramatically narrows the threat model.

The record format

example.com.  IN  CAA  <flag>  <tag>  "<value>"

The three tags that matter:

The flag is almost always 0 (advisory). 128 is the "critical" bit — if the CA doesn't understand the tag, it must refuse — but in practice not used.

The 3-line config that covers 95% of domains

example.com.  IN  CAA  0  issue      "letsencrypt.org"
example.com.  IN  CAA  0  issuewild  "letsencrypt.org"
example.com.  IN  CAA  0  iodef      "mailto:security@example.com"

"Only Let's Encrypt may issue certs for example.com or any subdomain wildcard. Notify security@ if anyone else tries." Replace letsencrypt.org with your CA of choice. The standard CA identifiers:

CAidentifier
Let's Encryptletsencrypt.org
Google Trust Servicespki.goog
DigiCertdigicert.com
Sectigosectigo.com
GlobalSignglobalsign.com
Amazon Trust Servicesamazontrust.com
Microsoft (Azure)microsoft.com

If you use multiple CAs, list each on its own row. Order doesn't matter.

Provider-specific notation

OVH, Cloudflare, Gandi etc. all expect form fields rather than BIND zone syntax. Mapping:

FieldValue
TypeCAA
Sub-domain (Name)blank (apex), or the subdomain
Flags0
Tagissue (or issuewild / iodef)
Valueletsencrypt.org (or the chosen CA)

Verifying with dig

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

TTL on CAA records is typically 24h. Changes propagate within that window. ACME issuance fetches CAA at request time, so an updated CAA blocks new issuance immediately.

Subdomain inheritance

CAA is inherited from parent zones (until overridden). A CAA at example.com covers www.example.com, api.example.com, etc. unless api.example.com has its own CAA. Useful pattern: tight CAA at apex, looser CAA on a specific subdomain that uses a different CA.

What can go wrong

  1. Forgetting issuewild. If you have issue letsencrypt.org only and try to renew a wildcard, LE refuses. Add issuewild too if you use wildcards.
  2. Account binding. Some setups bind CAA to a specific ACME account: 0 issue "letsencrypt.org;accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/12345". Stronger but requires syncing the account URI.
  3. Pointless quotes / typos. Validate with dig CAA after publishing. "letsencrypt.org " with trailing space breaks issuance silently.

UnveilScan's check

Our dns checker (Basic profile) emits dns.no_caa as MEDIUM when no CAA record is present at the apex. The Extended profile additionally validates the CAs listed against the actual issuers in your CT logs — if your CAA says "letsencrypt.org only" but crt.sh shows a Sectigo cert from last month, that's a CAA misconfiguration or a forgotten cert.

Check your CAA in 60 seconds

Free Basic scan reports CAA presence + recommends the canonical 3-line snippet.

Scan a domain