Safeguard
Supply Chain Security•

Certificate Transparency Monitoring After eMudhra: A Practical Guide

How to watch CT logs for certificates issued for your domains, set CAA records, and handle alerts, plus what the eMudhra case shows CT cannot catch.

Safeguard Security Team
21 min read

Certificate Transparency (CT) monitoring tells you when any public CA issues a certificate for your domains. After the eMudhra key compromise, it is cheap insurance every domain owner should run: query crt.sh today, set CAA records, and run a monitor such as Cert Spotter. It detects mis-issuance after the fact; it does not prevent it or protect non-browser clients.

Why CT came up in the eMudhra case

Eight eMudhra intermediate CA certificates were created in April 2025 with private keys so small that anyone could compute them from the public certificates. Browsers blocked the six TLS intermediates within hours of the 17 October report. Our eMudhra key compromise explainer covers the timeline and the trust store fixes. This post follows one thread: the part CT played, and how to use CT for your own domains.

Google's post on the block said no TLS certificate chaining to the six intermediates had been logged to CT before it acted. Because Chrome "enforces CT for all publicly trusted certificates by default," Google concluded no forged certificate from them could have worked against CT-enforcing clients. It also worked with log operators so CT logs would reject certificates chaining to the compromised CAs.

For an incident where nobody can know whether someone computed the keys during 17 months, CT is what lets anyone check whether a certificate from those intermediates was ever made public. CERT-In's advisory CIAD-2026-0050 accordingly tells administrators to watch CT logs for unauthorised issuance.

The other half matters as much. Scott Helme, who published the recovered key values, wrote that CT "detects mis-issuance though, it doesn't prevent it." He notes that curl, Python, Node, Go, Java, git and package managers do not check CT by default. A forged certificate that was never logged would still have worked on those clients, and monitoring your domains would not have shown it. CERT-In says CT monitoring "should supplement, rather than replace, certificate revocation and trust-store controls."

What happened, from the CT angle

Date (UTC)EventSource
30 Apr 2025Key generation ceremony creates the eight intermediateseMudhra, via Mozilla Bugzilla
May 2025Sectigo's AAA Certificate Services root cross-signs each intermediateScott Helme
17 Oct 2026, 18:05Chrome Root Program receives the reportGoogle
17 Oct, 19:45Chrome CRLSet blocks the six TLS intermediates by public key hashGoogle
18 OcteMudhra revokes all eight; says only EM DV TLS CA G3C went live and none issued end-entity certificatesMozilla Bugzilla, CERT-In
19 Oct, about 22:00Android receives the block through Google Play ServicesGoogle
21 OctCERT-In advisory recommends CT monitoring alongside trust store controlsCERT-In
27 Oct (expected)Chrome removes the emSign ECC Root CA G3Google

eMudhra's statement that no end-entity certificates were issued is its own claim on Bugzilla; the thread does not include a CT search backing it. Google's CT statement covers the six TLS intermediates. The other two signed code, which browser CT enforcement does not cover.

How Certificate Transparency works

CT is a set of public, append-only logs of certificates. The project's explainer at certificate.transparency.dev describes the moving parts:

  1. Logs. Independent operators run them. Entries can be added but not removed or changed, and signed Merkle tree heads make tampering detectable.
  2. Precertificates. Before issuing, a CA submits a precertificate (a copy with a poison extension browsers reject) to logs.
  3. SCTs. Each log returns a Signed Certificate Timestamp, a promise to include the entry within its Maximum Merge Delay, usually 24 hours. The CA embeds SCTs in the certificate.
  4. Monitors. Anyone can watch logs. Domain owners can subscribe and be notified when a certificate or precertificate for their names appears.

Chrome's CT policy requires embedded SCTs from two qualifying logs for certificates valid up to 180 days and three for longer ones, from at least two operators. Certificates that fall short "will simply fail to validate in CT-enforcing versions of Chrome." So a certificate meant to work in a modern browser has to appear where you can see it.

Which clients actually check CT

ClientChecks CT?Source
Chrome desktopYes, for all publicly trusted certificates by defaultGoogle
Android appsYes if they target the latest SDK or opt inGoogle
Firefox, SafariYesScott Helme
curl, Python, Node, Go, Java, git, package managersNot by defaultScott Helme
mTLS servers checking client certificatesUsually notCheck your stack
Appliances, IoT, embedded firmwareAssume notAsk the vendor

Chrome's policy also lets enterprise administrators disable CT enforcement for certain CAs or URLs. If yours does, the browser row does not fully apply.

Step 1: See what is already logged for your domains

Start with a one-off search: which CAs have issued for you, and does anything chain to a hierarchy you do not use?

crt.sh

crt.sh is a free CT search engine. Sectigo says its engineer Rob Stradling built and maintains it, and that it searches by domain, organisation, fingerprint or crt.sh ID. A % acts as a wildcard and output=json returns machine-readable results.

# Unexpired certificates for example.com and its subdomains
curl -s 'https://crt.sh/?q=%25.example.com&output=json&exclude=expired' \
  | jq -r '.[] | [.entry_timestamp, .issuer_name, .name_value] | @tsv' \
  | sort -u > ct-example.tsv

# Which issuers have you used?
cut -f2 ct-example.tsv | sort | uniq -c | sort -rn

# Anything from the eMudhra hierarchy?
grep -i -E 'emudhra|emsign' ct-example.tsv

If the last command prints anything, check what you actually serve with the openssl s_client command in the parent post and replace those certificates before Chrome's root removal, as Google advises.

crt.sh is a shared service and large queries time out. When we tried it on 21 October it returned HTTP 502 errors. Retry later, narrow the query, or use a second source.

Cert Spotter's search API

SSLMate, which develops Cert Spotter, runs a search API. Its docs allow unauthenticated queries for personal or evaluation use at a limited hourly rate; production use needs an API key.

curl -s 'https://api.certspotter.com/v1/issuances?domain=example.com&include_subdomains=true&match_wildcards=true&expand=dns_names&expand=issuer' \
  | jq '.[] | {id, not_before, dns_names, issuer}'

Results are paged: pass the last id as after= for the next page.

Step 2: Set CAA records

CAA is a DNS record naming the CAs allowed to issue for your domain, defined in RFC 8659 (which obsoleted RFC 6844). Before issuing, a public CA finds the closest CAA record set by climbing from the requested name toward the root.

example.com.  3600  IN  CAA  0 issue "letsencrypt.org"
example.com.  3600  IN  CAA  0 issue "your-second-ca.example"
example.com.  3600  IN  CAA  0 issuewild ";"
example.com.  3600  IN  CAA  0 iodef "mailto:security@example.com"
  • issue authorises a CA by its CAA identifier, which each CA documents (Let's Encrypt's is letsencrypt.org).
  • issuewild ";" forbids wildcards. RFC 8659 says issuewild, when present, takes precedence for wildcard requests. Drop it if you use wildcards and name the CA that issues them.
  • iodef gives CAs an address for reporting policy violations.

Let's Encrypt documents two RFC 8657 extensions that narrow things further:

example.com. IN  CAA  0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890"
example.com. IN  CAA  0 issue "letsencrypt.org; validationmethods=dns-01"

accounturi limits issuance to one ACME account; validationmethods limits challenge types. Check your records with dig +short CAA example.com, and repeat for important subdomains, since a subdomain record overrides its parent.

What CAA would not have done here

CAA is checked by a CA's issuance system before it signs. RFC 8659 says browsers must not use CAA when validating certificates, and that CAA does not stop an authorised CA from misissuing.

Someone holding a computed eMudhra intermediate key would not touch eMudhra's issuance system. They could sign a certificate on a laptop with no CAA check. CAA would not have stopped forgery in this case.

It is still worth having. It blocks more common failures: a CA you do not use being fooled by a validation attack, a team buying from an unapproved vendor, or a forgotten SaaS integration requesting certificates for your names.

Step 3: Run a monitor continuously

Searches cover the past; a monitor covers tomorrow. The options below are free or open source, described from their own documentation and not ranked.

OptionWhat it isAlertsNotes from its docs
Cert Spotter (open source)Self-hosted monitor from SSLMate, MPL-2.0Email via sendmail, hook scriptsNo database needed; understands wildcards; watches logs on the Chrome and Apple log lists
Cloudflare CT MonitoringOpt-in dashboard feature for domains on CloudflareEmailFilters out certificates Cloudflare issues for you; does not detect lookalike domains
certstream-pythonMIT-licensed client for an aggregated CT streamYour callback codeYou write the matching; no stated uptime or completeness guarantee for the public server
crt.shFree search engineNone; you pollGood for backfill and spot checks

Setting up Cert Spotter

It needs Go 1.21 or newer.

go install software.sslmate.com/src/certspotter/cmd/certspotter@latest

mkdir -p ~/.certspotter/hooks.d
cat > ~/.certspotter/watchlist <<'EOF'
.example.com
.example.net
login.partner-portal.example.org
EOF
echo "pki-alerts@example.com" > ~/.certspotter/email_recipients

certspotter -start_at_end

A leading dot watches the domain and all subdomains; a name without it watches only that name. The README suggests -start_at_end to save bandwidth, at the cost of missing anything logged earlier, which is why the Step 1 backfill comes first. Run it under systemd or another supervisor and check the README for current flags.

A triage hook

Cert Spotter passes event details to scripts in ~/.certspotter/hooks.d as environment variables, including EVENT, ISSUER_DN, CERT_SHA256, PUBKEY_SHA256 and JSON_FILENAME, a file whose dns_names array holds the certificate's names. A useful pattern is matching the certificate's public key against keys you generated.

#!/bin/sh
# ~/.certspotter/hooks.d/triage  (make it executable)
[ "$EVENT" = "discovered_cert" ] || exit 0
names=$(jq -r '.dns_names | join(",")' "$JSON_FILENAME")
if grep -qi "$PUBKEY_SHA256" "$HOME/.certspotter/known-pubkeys.txt" 2>/dev/null; then
  level=info
else
  level=page   # forward these to on-call
fi
printf '%s\t%s\t%s\t%s\n' "$level" "$names" "$ISSUER_DN" "$CERT_SHA256" >> "$HOME/ct-alerts.tsv"

Build the known keys file from your own certificates, and compare the format against one real alert before relying on it. If your ACME client rotates keys at renewal, update the file from the renewal hook.

openssl x509 -in fullchain.pem -noout -pubkey \
  | openssl pkey -pubin -outform DER | openssl dgst -sha256 -r | cut -d' ' -f1

Do not route on issuer name alone. Cert Spotter's docs warn the issuer field is CA-controlled and can be misleading.

Step 4: Handle an alert

Most alerts are legitimate; Cloudflare's docs suggest acting only when something looks wrong. Work in order:

  1. Read the facts: names, issuer, dates, log entry. A precertificate is usually followed by its final certificate; that is one event, not two.
  2. Check your records: ACME logs, certificate inventory, CDN and SaaS accounts that can request certificates for you.
  3. Check the key. A match with a key you hold means the request came from someone with that key.
  4. Check CAA. If the issuer was not allowed at the time, the CA issued against your policy.
  5. Contact the issuing CA. Cloudflare's docs note the CA is the only party that can revoke. Send the crt.sh ID or SHA-256 fingerprint to the problem reporting contact in its CPS.
  6. Find the cause: a dangling DNS record, a hijacked web server, a compromised DNS account or a stolen ACME key. Fix it before rotating, or it recurs.
  7. If the issuer itself looks wrong, such as an unknown intermediate under a public root, report it to the browser root programs too. That is how the eMudhra report reached Mozilla and Google.

What CT cannot catch

GapWhyWhat covers it
Forged certificates never loggedA CA key holder can mint one for clients that skip CT, as Helme showed for curl, Python and NodeCurrent trust stores, revocation, rebuilt images
Detection delayInclusion is promised within the merge delay, usually 24 hoursCAA to limit issuance up front
Private and enterprise CAsNot publicly loggedYour own issuance logs
Most mTLS client certificatesOften issued outside public CTTrust only your own CA for client auth
Code-signing certificatesBrowser CT covers TLS server certificatesSignature and provenance checks
Lookalike domainsMonitors watch your names, not similar onesSeparate brand monitoring
Certificates from a real validation holeLogged, but look legitimateKey matching and accounturi

The first row is the eMudhra lesson. For browsers, CT and Google's statement settled the question. For your other software, only trust store updates did.

What would have helped

Practices any team can use

Monitor before you need it. Teams with alerts already running could answer "has anything been issued for our names?" in minutes during the eMudhra news.

Keep a certificate inventory. List the CAs, ACME accounts, CDN and SaaS providers allowed to request certificates for each domain. Most alerts become a two-minute check.

Keep CAA in code. Store CAA with the rest of your DNS so changes get reviewed, and add accounturi for your main ACME account.

Treat trust stores as dependencies. CT cannot do this part. Every image, runtime and binary carrying a CA bundle needs an update path; our SBOM incident response guide shows how to find them fast. For background, see what a certificate authority is and certificate authority compromise risks.

Where Safeguard fits

Safeguard does not monitor CT logs, check CAA records or track the TLS certificates you hold; use the tools above. It cannot see a CA's key ceremony and would not have prevented this incident. It helps with the half CT cannot cover:

  • Finding stale trust bundles. SBOM and dependency scanning covers repos, images and SBOM files (safeguard scan --dir ., --image <name>, --sbom <file>, JSON under ./output). The platform shows which projects contain a given component and version, so "which images carry an old ca-certificates package" becomes a query.
  • Holding old versions back with policies and gates evaluated in the platform.
  • Doing the work. The Safeguard CLI assistant edits code and runs commands with your approval: adding a Cert Spotter hook to a config repo, CAA records to DNS-as-code, or a base image bump and rebuild. Autonomous remediation can open fix PRs; it ships off by default.

Zero-Day Discovery and Gold

Zero-Day Discovery looks for previously unknown flaws before a CVE exists, in an agentic mode and a deterministic scanner mode, and issues findings as SGZ advisories before they reach public CVE databases. It covers seven package ecosystems.

Gold Open Source (gold.safeguard.sh, free, no login) offers searchable CVE intelligence with CVSS, EPSS, KEV status, affected and fixed versions and a recommended safe version, a free read API and a CI gate GitHub Action. The sources we reviewed cite no CVE for the eMudhra keys, so there is nothing to look up there.

Gold Registry (registry.safeguard.sh, paid) provides hardened drop-in components and container images held to zero exploitable critical or high CVEs, SLSA L3 or higher, Sigstore-signed, with evidence pages; an artifact loses its badge on regression. We are not claiming it shipped an eMudhra fix. The habit it supports is the one that mattered: pull patched, signed components from a curated source and rebuild fast when trust stores change.

Common mistakes

  • Watching the apex only. Without the leading dot, api.example.com is missed.
  • Forgetting domains. Old brands, country domains and partner portals count. Pull the list from your registrar.
  • Alerts to a dead mailbox. Route high-priority events to on-call.
  • Starting at the end with no backfill. Search history first.
  • Treating CT as prevention. Clients that skip CT get nothing from it.
  • CAA that breaks vendors. A SaaS provider issuing for a subdomain needs its CA allowed for that name.
  • Disabling verification to clear errors. Cloudflare's eMudhra post warns against it.

FAQ

Would CT monitoring have warned me about a forged eMudhra certificate for my domain?

Only if it had been logged. Google says nothing chaining to the six TLS intermediates was logged before its block. A forger targeting non-browser clients has no reason to log, which is why trust store updates were the real fix.

What did Chrome's statement prove?

That no forged certificate from those intermediates could have been accepted by CT-enforcing clients such as Chrome. It says nothing about clients that skip CT, such as default curl, Python or Node.

Is crt.sh enough on its own?

It is good for history and spot checks and it is free, but it is shared, sometimes times out, and sends no alerts. Pair it with a monitor.

Will CAA records stop a compromised CA?

No. CAA is checked by an honest CA's issuance system. A CA key holder can sign without any CAA lookup, and browsers do not check CAA.

How noisy is CT monitoring?

It depends on volume. ACME renewals are frequent and each usually logs a precertificate and a certificate. Matching on your own keys filters most of it.

My site has an eMudhra certificate. How does CT help?

Search CT for every certificate for your names that chains to the emSign ECC Root CA G3, including forgotten hosts. Google advises replacing them from another hierarchy before the expected 27 October removal.

Fix it without waiting for upstream

In incidents like this one, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would have helped

The CLI demo is a real session fixing a lodash CVE: it reads the finding, asks before each command, edits package.json and runs install and tests with your approval. After eMudhra, you would use the same loop to ask it to bump a service's base image and certifi pin, rebuild, and rerun your TLS test. The demo does not show this incident.

Click through it at your own pace, or open it full screen.

The desktop app demo shows a CLI session in the conversation list, a request for work on your computer, a folder choice, and Approve or Deny on each command and file edit, ending with an upgrade done and tests passing. The same flow fits adding the Cert Spotter hook and CAA records to your config repository, reviewing each edit before it lands.

Click through it at your own pace, or open it full screen.

The mobile demo is a real Android session: work goes to a computer running the CLI and you approve the command on the phone with Allow once, Allow for turn or Deny. If a CT alert lands at night and the fix is a rebuild, this is how you would approve it without a laptop.

Click through it at your own pace, or open it full screen.

To find every image and service that still ships an old CA bundle, download Safeguard and follow the CLI docs. For the rest of the month, see October 2026 security incidents and what would have helped.

Quick check

Google says nothing from the six eMudhra TLS intermediates was logged in CT. Were your Python services therefore never at risk?

No. That protects CT-enforcing clients such as Chrome. Python, curl and Node do not check CT by default, so an unlogged forged certificate could have worked on them until their CA bundles were updated and services rebuilt.

Would a CAA record allowing one CA have stopped someone holding a computed eMudhra intermediate key?

No. CAA is checked by a CA's issuance system. A key holder signs directly with no CAA lookup, and browsers do not check CAA. CT monitoring and trust store updates cover what CAA cannot.

Sources

Last reviewed: 21 October 2026. This is a developing story; check the linked advisories for the latest status.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.