Every publicly trusted TLS certificate issued since 2018 gets written to a Certificate Transparency (CT) log before a browser will accept it without a warning. That single requirement turned CT logs into the most complete, most current public record of an organization’s internet-facing hostnames, more current in practice than most internal CMDBs. If a developer spun up staging-payments.example.com last month and forgot to tell anyone, the certificate request already told the world.
What CT logs are and why they are public by design
Certificate Transparency (RFC 6962, extended by RFC 9162) is an append-only, cryptographically verifiable log of certificates. Log operators, including Google (Argon, Xenon), Cloudflare (Nimbus), DigiCert, and Sectigo, run independent log servers. When a certificate authority issues a certificate, it submits it to one or more of these logs and receives a Signed Certificate Timestamp (SCT) back, which the CA embeds in the certificate or delivers via OCSP stapling. Chrome, and now most major browsers, will not trust a certificate that lacks a valid SCT from a qualifying log.
The design intent was to make mis-issuance detectable: if a CA is compromised or coerced into issuing a certificate for a domain it should not, the domain owner (or anyone monitoring the logs) can see it. The side effect is that every certificate, including ones for internal tools accidentally exposed to the internet, staging environments, forgotten proof-of-concept apps, and acquired subsidiaries, becomes queryable by anyone. You do not need credentials, an NDA, or a bug bounty scope to read them. Public search front ends such as crt.sh, Censys, and CertStream index the logs so you do not have to parse the Merkle tree yourself.
Extracting assets from the records: SAN fields, issuance time, and issuing CA
Three fields do almost all the useful work when you are mining CT data for asset discovery:
- Subject Alternative Name (SAN): modern certificates carry hostnames here, not in the Common Name. A single certificate can list dozens of SAN entries across unrelated-looking subdomains, which is often how you find a naming convention or an internal codename leaking into production.
- not_before / issuance timestamp: tells you when the hostname first appeared, which matters for correlating with a deployment, an acquisition, or an incident window.
- Issuing CA and log operator: a hostname issued by an unfamiliar CA, or one that does not match your organization’s usual certificate management tooling (ACME client, internal PKI proxy, cloud load balancer default), is worth checking for shadow IT or a rogue deployment outside your normal pipeline.
A practical starting query against crt.sh’s JSON output looks like this:
curl -s "https://crt.sh/?q=%25.example.com&output=json" | jq -r '.[].name_value' | tr ',' 'n' | sed 's/^*.//' | sort -u > ct_hostnames.txt
That pulls every SAN entry ever logged for *.example.com, strips the wildcard prefix, deduplicates, and gives you a flat hostname list. From there, resolve each name and diff it against your known asset inventory:
while read -r host; do dig +short "$host" A AAAA done < ct_hostnames.txt > resolved.txt
Hostnames that resolve but do not appear in your asset inventory are your candidate list. Hostnames that do not resolve at all are not necessarily dead: they may point to a decommissioned CDN entry, a lapsed cloud load balancer, or a domain takeover opportunity if the DNS record still exists and points to an unclaimed cloud resource.
Certificate transparency monitors versus one-off queries
A one-time crt.sh pull is a snapshot. For ongoing discovery you want a monitor: CertStream provides a real-time WebSocket feed of every certificate as it is logged, and crt.sh supports scheduled queries via its own API rate limits. Most attack surface programs settle on a daily or hourly diff job: pull the current SAN set for each root domain you own, compare it against yesterday’s set, and alert only on the delta. That keeps the signal-to-noise ratio workable once you are watching more than a handful of domains.
The attacker uses the same source: internal name leakage risk
Nothing about CT log access is privileged. A reconnaissance script run by an external attacker uses the exact same crt.sh query you just ran. This has a specific consequence worth internalizing: any naming convention that leaks through a certificate SAN is now attacker knowledge, permanently, because CT logs are append-only and cannot be retracted.
Common leakage patterns worth auditing for in your own certificate history:
- Internal project or codename fragments in hostnames (
vpn-project-falcon.example.com), which hint at what is being built before an announcement. - Environment markers that reveal architecture (
db-replica-2.internal.example.comissued for a certificate that should never have needed a publicly trusted CA in the first place). - Acquisition or divestiture signals: a certificate for a target company’s domain issued under the acquirer’s certificate management account, months before a public announcement.
- Sequential or predictable naming (
app01throughapp47) that lets an attacker infer the existence of hosts they have not directly observed.
None of this is a flaw in Certificate Transparency; it is a flaw in treating certificate issuance as an operational afterthought. The fix is not to avoid CT (you cannot, if you want a browser-trusted certificate) but to treat your own certificate issuance stream as a data source you monitor as closely as an outsider would.
Reducing the noise: wildcards, shared CDN certificates, and renewal repetition
Raw CT output for an active domain is noisy in three specific ways, and each has a specific filter:
| Noise source | What it looks like | How to filter it |
|---|---|---|
| Wildcard certificates | *.example.com appears once but covers an unbounded set of subdomains |
Flag wildcards separately; they confirm a zone is covered but do not enumerate live hosts, so you still need DNS brute-forcing or passive DNS to find what sits under them |
| Shared CDN or SaaS certificates | A single certificate lists your domain alongside dozens of unrelated customer domains on the same CDN edge (Cloudflare, Fastly, Akamai) | Match against known CDN issuer patterns and SAN list size; a certificate with 90 unrelated SAN entries is a shared edge certificate, not evidence of a related asset |
| Renewal repetition | The same hostname re-issued every 60 to 90 days under Let’s Encrypt or a similar short-lived CA | Group by hostname and keep only the most recent issuance per host before diffing; do not alert on a renewal as if it were a new asset |
A workable dedup rule: group SAN entries by normalized hostname, keep the row with the latest not_before, and only carry forward hosts whose first-seen date falls inside your lookback window. That alone typically cuts a raw crt.sh export by 70 to 90 percent for a domain with automated certificate renewal. Some platforms that automate this stage, SITEY among them, group SAN entries by issuer, key, and renewal cadence automatically so an analyst reviews a deduplicated candidate list instead of a raw log dump.
Turning a CT finding into inventory: verification and ownership
A hostname appearing in CT logs is a lead, not a confirmed asset. Before it goes into your inventory as something you are responsible for patching, run it through a short verification sequence:
- Resolve it. Does the hostname currently resolve to an IP you control, a cloud provider range you use, or a CDN you have a contract with?
- Fingerprint the service. An HTTP banner grab, TLS handshake, or a lightweight scan tells you whether something is actually listening, and what.
- Check ownership signals. Cloud tags, WHOIS on the parent domain, the internal team that requested the certificate (if your CA issuance is logged internally), or the git repository that references the hostname in its deployment config.
- Assign an owner before closing the loop. An asset with no owner will not get patched when a vulnerability shows up against it later; it just sits as an orphaned entry that reappears in the next audit.
This is the step where CT-derived leads either become durable inventory or get closed as false positives (a decommissioned host, a partner’s certificate that happened to reference your domain in a SAN by mistake, a test certificate never deployed). Skipping verification and dumping raw CT matches straight into a vulnerability scanner produces exactly the kind of noisy, unowned finding list that erodes trust in the whole discovery process. Feeding confirmed hostnames into a scan management queue only after ownership is established keeps the scanning workload proportional to real risk rather than to log volume. Discovery platforms built around continuous attack surface management, including SITEY, run this resolve-fingerprint-assign sequence as a standing pipeline stage rather than a manual quarterly exercise, so a new SAN entry becomes a triaged asset inventory record within the same discovery cycle instead of sitting in a spreadsheet.
What CT logs cannot find: certificate-less services and internal systems
CT is a certificate-issuance log, not a network map, and it has real blind spots:
- Anything without a publicly trusted certificate. Plain HTTP services, raw TCP services (databases, message queues, RDP, SSH), and internal services fronted only by self-signed or private-CA certificates never touch a public CT log.
- Internal PKI. Enterprises running their own internal certificate authority for intranet services generate certificates that are never submitted to public logs, by design.
- Certificates issued but never deployed. A CT entry proves a certificate was requested and logged, not that anything is running on that hostname.
- IP-only exposure. Services reachable only by IP address, with no hostname or certificate at all, are invisible to CT-based discovery entirely.
Because of these gaps, CT log mining works best as one input among several: passive DNS, active subdomain brute-forcing, cloud asset APIs (which see resources regardless of whether they carry a certificate), and network-level port scanning against your known IP ranges. An attack surface program that relies on CT logs alone will systematically miss exactly the kind of asset that is most likely to be forgotten: an internal-facing database left with a public IP and no TLS at all. This is why platforms built for attack surface work, SITEY included, correlate CT log matches with cloud API inventories and network reachability data rather than treating certificate issuance as the sole discovery signal; a hostname that shows up in a certificate but never in a live network scan gets flagged differently than one that shows up in both.
The practical takeaway for a team running this themselves: schedule the crt.sh or CertStream pull as a recurring job, dedup aggressively before anyone looks at the output, verify ownership before anything gets marked as inventory, and pair it with at least one discovery method that does not depend on TLS. CT logs will reliably surface the subdomain someone forgot to decommission; they will just as reliably stay silent about the database someone forgot to put behind a certificate at all.
About SITEY
SITEY is an autonomous vulnerability management platform. It discovers, validates, prioritizes, remediates and re-tests vulnerabilities through an eight-phase automated pipeline, unifying output from 17 integrated scanners. SITEY is self-hosted: it runs in your own infrastructure and your findings are stored there. Outbound connections are limited to licence activation and the optional services you enable, such as an AI provider, CVE enrichment and patch catalogues. Pricing is 599 USD per month or 5,999 USD for a perpetual lifetime license. See pricing or how the platform works.