Certificate Transparency Monitoring: Catching Unexpected Certificates for Your Domains
Someone can mint a publicly trusted certificate for your domain without ever touching your servers. Mis-issuance, a shadow IT ACME client, a forgotten staging hostname, or an attacker who briefly controlled DNSβall of th
Someone can mint a publicly trusted certificate for your domain without ever touching your servers. Mis-issuance, a shadow IT ACME client, a forgotten staging hostname, or an attacker who briefly controlled DNSβall of them show up in Certificate Transparency logs if you are looking. Most teams only discover the surprise cert when a browser warning, a customer email, or a bug bounty report arrives. CT monitoring turns that into a same-day alert instead of a postmortem slide.
I wrote this with help from AI tools and checked every command and claim myself against current CT tooling. I build PixelValut, a set of free browser-based developer and network tools, and this is Part 4 of Web PKI & Certificate Forensics in Practice. Part 1 covered leaked private keys and safe rotation. Part 2 taught reading X.509 by hand. Part 3 covered revocation realities in 2026. Here we watch the public ledger of issuance.
π Series Roadmap β Web PKI & Certificate Forensics in Practice
- Part 1: Leaked TLS Private Keys: Proving Compromise, Finding Every Affected Cert & Rotating Safely
- Part 2: Reading X.509 Certificates by Hand: SANs, Key Usage, Chains & Intermediates
- Part 3: Certificate Revocation in 2026: CRLs, the Decline of OCSP & Short-Lived Certificates
- Part 4 (This Post): Certificate Transparency Monitoring: Catching Unexpected Certificates for Your Domains
- Part 5: ACME Automation Failures: Renewal Outages, Rate Limits & DNS-01 Pitfalls
- Part 6: Mutual TLS for Internal APIs: Private CAs, Rotation & Pinning Trade-offs
How do you monitor Certificate Transparency for unexpected certs?
Direct answer: Subscribe to CT alerts for your registered domains (and critical subdomains), baseline the CAs and ACME accounts you expect, and treat every new precertificate as an incident until proven routine. Query public CT search APIs regularly, page on unknown issuers or SANs, then rotate and revoke using the playbooks from Parts 1 and 3 when the issuance was not yours.
What Certificate Transparency actually gives you
CT is an append-only log ecosystem. Public CAs submit precertificates so browsers can require proof of logging. For operators, the useful property is discoverability: if a trusted CA issued a leaf covering *.example.com or api.example.com, that issuance is searchable.
| Source of surprise cert | Typical signal in CT | First response |
|---|---|---|
| Attacker with brief DNS control | New leaf from unexpected CA / ACME | Assume key may exist; replace + revoke |
| Shadow IT / forgotten staging | Hostname you do not run in prod | Inventory owner; tighten ACME DNS access |
| CDN or SaaS onboarding | Expected partner CA, new SAN set | Confirm ticket; add to allowlist |
| CA mis-issuance | Domain you own, CA you never used | Escalate to CA + browser programs as needed |
| Wildcard you forgot existed |
*.example.com still valid |
Schedule replacement; shrink scope |
CT does not stop issuance. It tells you issuance happened. Pair it with DNS lock-down (CAAβmore below), short-lived certs from Part 3, and key-compromise response from Part 1.
Baseline before you alert
Noise kills CT programs. Spend one afternoon building an allowlist:
EXPECTED
- Domains: example.com, *.example.com, api.example.com, staging.example.com
- CAs: Let's Encrypt R3/E1 (or your current intermediates), your paid EV/OV CA if any
- Issuance pattern: ACME from CI account X, renewals every 60 days
- Known partners: CDN-managed certs for www (ticket #β¦)
UNEXPECTED (page immediately)
- Any other CA
- SANs outside inventory
- Wildcard you thought you retired
- Same hostname from two CAs in the same week without a migration ticket
Querying CT in practice (crt.sh and friends)
The classic public search interface is crt.sh. Examples you can run today:
# Recent certificates mentioning your domain (HTML/JSON endpoints exist)
curl -sS "https://crt.sh/?q=%25.example.com&output=json" \
| jq -r '.[].name_value' | sort -u | head
# Narrow by identity string
curl -sS "https://crt.sh/?q=api.example.com&output=json" \
| jq -r '.[] | [.not_before,.issuer_name,.name_value] | @tsv' \
| sort | tail -n 20
For automation, prefer authenticated CT monitoring products or your own log followers if you operate at scale; crt.sh is excellent for investigation and light polling, not as a sole production pager. When you pull a serial, inspect the leaf the same way as Part 2:
# After downloading a PEM from CT / CA
openssl x509 -in surprise.pem -noout -subject -issuer -dates -ext subjectAltName
While you triage, an SSL checker shows what your edges currently serve; a DNS lookup confirms whether the surprise hostname still resolvesβand to whom. I build PixelValut; use those views as a second opinion beside OpenSSL and CT search, not as the only control.
CAA records: reduce issuance, still monitor CT
CAA tells CAs which issuers are allowed. It cuts accidental and some malicious issuance paths. It does not replace CT monitoringβCAs can fail open on lookup errors, and historical leaves remain in logs.
# Check CAA
dig example.com CAA +short
# Example allow-only Let's Encrypt:
# example.com. CAA 0 issue "letsencrypt.org"
# example.com. CAA 0 issuewild "letsencrypt.org"
Operational rule: set CAA deliberately, monitor CT anyway, and alert when a logged cert's issuer is outside your CAA intent (that combination is a serious smell).
A minimal monitoring loop you can ship this week
- Inventory every public hostname that should ever get a cert (include wildcards).
- Subscribe to CT alerts (email/Slack/webhook) for those namesβcommercial monitors or self-hosted log watchers.
- Deduplicate by fingerprint/serial so renewals from the expected ACME account do not wake humans at 3 AM.
- Enrich alerts with issuer, SANs, notBefore, and whether the name resolves.
- Triage within your Sev definitions: unknown CA = high; expected CA + unknown SAN = medium; known renewal = auto-close.
- Respond with Part 1 rotation if private key exposure is plausible; Part 3 revoke after replacement.
- Feed lessons into ACME hardening (Part 5)βDNS-01 credentials are frequent root causes.
# Sketch: poll crt.sh JSON and diff against an allowlist file
# (production: use authenticated APIs, retries, and a real datastore)
import json, urllib.request
def names_for(domain: str) -> set[str]:
url = f"https://crt.sh/?q=%25.{domain}&output=json"
data = json.load(urllib.request.urlopen(url, timeout=60))
out: set[str] = set()
for row in data:
for part in row.get("name_value", "").split("\n"):
out.add(part.strip().lower())
return out
allow = {"example.com", "www.example.com", "api.example.com"}
found = names_for("example.com")
print("unexpected:", sorted(found - allow))
Treat that sketch as a spike. Rate limits, pagination, and false positives from internal test domains will force a real pipeline quickly.
Correlating CT hits with live edges
A CT hit means a cert was logged. It does not mean every CDN POP serves it.
# What does the world see on 443 right now?
echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
| openssl x509 -noout -serial -issuer -dates -ext subjectAltName
Compare serials. During migrations you may legitimately see two CAs. Document the window. Outside a migration, dual issuance is either CDN complexity or an incident.
Privacy and ethics note
CT logs are public by design. Do not use monitoring access to harass unrelated domains. Scope alerts to names you own or are contracted to protect. Precertificates can reveal internal hostnames earlyβassume attackers read the same logs.
Diagnostic checklist
- Do you have an inventory of every public hostname (and wildcards) that may receive a cert?
- Are CT alerts wired to a human-pageable channel with quiet hours + severity rules?
- Is there an allowlist of expected CAs and ACME identities?
- Do renewals auto-suppress so only novel issuances alert?
- Is CAA published and aligned with that allowlist?
- Can you pull SAN + issuer + serial from an alert within five minutes?
- Does triage include DNS resolution and live
openssl s_clienton each edge? - Is the Part 1 key-compromise playbook linked from the CT runbook?
- Is the Part 3 revoke-after-replace sequence linked and rehearsed?
- Are shadow subdomains from CT feeding your takeover / dangling DNS review?
FAQ
Does CT monitoring replace CAA?
No. CAA reduces who may issue; CT tells you who did. Run both.
Will Let's Encrypt renewals flood my pager?
They will if you alert on every precertificate. Deduplicate by expected issuer + hostname pattern + timing window.
Are private / internal CA certs in CT?
Generally noβCT focuses on publicly trusted logs. Internal mTLS (Part 6) needs separate inventory and monitoring.
What if crt.sh is down?
Have a second source (another CT search, a commercial monitor, or your own log follower). Incidents do not wait on one website.
Should I revoke every unexpected cert automatically?
Replace first when you control the name, then revoke. Automatic revoke bots without human triage can fight a legitimate migration. Automate detection; keep a human in the destructive loop until the playbook is battle-tested.
How fast should we respond?
Treat unknown-CA issuance like credential exposure: same-day investigation at minimum, faster if the hostname is auth-sensitive. Short-lived certs shrink the window but do not excuse slow triage.
Next in this series, Part 5 covers ACME automation failuresβrenewal outages, rate limits and DNS-01 pitfalls that often explain the "surprise" certs CT just showed you.
Follow & Connect
- Website: PixelValut Tools
- YouTube: PixelValut (@pixel-valut)
- TikTok: PixelValut (@pixelvalut007)
- GitHub: Muhammad Ali Mughal (@ali111887)
- LinkedIn: Muhammad Ali Mughal
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.