Every subdomain you own is already public
Certificate Transparency logs, crt.sh, and what to do on the mornings the web UI answers 502
The internal tool was on grafana-staging.example.com, behind the VPN, no public DNS record, not linked from anywhere. Someone asked whether it was really invisible. It took about fifteen seconds to prove it wasn't: the hostname was sitting in a public log, along with every other name we'd ever requested a certificate for.
Nobody leaked it. The certificate authority published it, because that's the deal.
The deal
Certificate Transparency means every publicly trusted TLS certificate gets written to append-only public logs at issue time. Browsers enforce it - a certificate that isn't in the logs doesn't get trusted, so there's no opting out while still having a working site.
The reason it exists is sound. Before CT, a CA could mis-issue a certificate for your domain and nobody would find out until it was used against someone. Now the mis-issuance shows up in a public log within hours, and the affected party can see it.
The side effect is the part most teams never think about: the log includes the hostnames. Every internal-sounding name you put in a SAN field is published, permanently, to anyone who cares to read.
What that means in practice
Type a domain into crt.sh and you get its certificate history. Use % as a wildcard - %.example.com - and you get every subdomain that has ever appeared in a certificate, including the ones that stopped existing years ago.
For an attacker doing reconnaissance this is the first stop, and it's free. vpn., jenkins-old., admin-staging., the hostname of the acquisition you haven't announced yet - all of it, sorted by date. It costs nothing and touches none of your infrastructure, so there's nothing to detect and nothing to rate-limit.
The defensive uses run on the same data. Watch the logs for certificates issued on names that look like yours and you catch phishing infrastructure during setup rather than during the incident - example-login.com getting a certificate is someone building the page they intend to send your customers to. Watch your own domains and you catch the certificate a team issued outside the process, from a CA you don't use.
When the front page is down
Here's the operational bit, and it's the reason I'm writing this one now: crt.sh is a single popular free service with a very large database, and it falls over regularly. On the morning I wrote this, both the web UI and the JSON endpoint were returning 502.
Two things still work when that happens.
The database is separately reachable. crt.sh exposes read-only Postgres, and it was answering while the web tier returned 502:
psql "postgresql://guest@crt.sh:5432/certwatch"Now the part that will save you twenty minutes, because every guide on the internet still gets it wrong. The canonical example everyone copies queries a certificate_identity table. That table is gone, and the error message tells you why:
ERROR: Sorry, the "certificate_identity" table has been superseded
by a Full Text Search index on the "certificate" table.The working shape uses that index instead:
SELECT c.id, x509_commonName(c.certificate)
FROM certificate c
WHERE plainto_tsquery('example.com') @@ identities(c.certificate)
LIMIT 100;Run that against kubernetes.io and among the first rows you get spartakus.k8s.io - a telemetry project that was shut down years ago, its hostname still sitting in the log where anyone can read it. That's the whole argument of this issue in one row.
Queries here are a language rather than a URL, so you can ask what the web form can't: group by issuer, filter by validity window, match a pattern across several registered domains in one pass. Set a statement_timeout and keep them narrow - broad ones get cancelled under load, which I also found out the direct way.
The other option is a different reader of the same logs. Cert Spotter's API takes a domain and returns issuances as JSON:
curl "https://api.certspotter.com/v1/issuances?domain=example.com\
&include_subdomains=true&expand=dns_names"The logs themselves are the source of truth. crt.sh, Cert Spotter, Censys - they're all just indexes over the same public data, so when one is down you switch rather than wait.
The limits worth knowing
There's a lag between issuance and the record showing up in an index - usually minutes, sometimes hours. So for monitoring, alerting off a poll of an index is fine; treating its absence as proof that no certificate exists is not.
Private PKI is invisible here, by definition. If you run an internal CA for internal names, none of that reaches the public logs - which is also the practical mitigation for the problem this whole issue describes.
And wildcard certificates hide names rather than reveal them: a certificate for *.example.com publishes exactly one string. Teams that switch to wildcards for this reason are trading one exposure for a bigger blast radius on key compromise, which is a real trade, not an obvious win.
What I'd actually do
Run the wildcard query against your own domains this week and read the list properly. It is, at minimum, an accurate inventory of hostnames you've ever certified - and in my experience it always contains something nobody remembers creating.
Then set up monitoring on names close to yours, so brand-lookalike certificates page someone at issue time rather than after the phishing run starts. Cert Spotter and Censys both do this on a schedule; the free tiers cover a small domain list.
And when you name the next internal host, remember the name is going in a public log the moment it gets a certificate. admin-legacy-payments.example.com tells a stranger quite a lot.
Links
Questions? Feedback? Reply to this email. I actually read them.
- Ilia



