Ask any security team what they monitor for a domain and the answer is almost always the same list: SSL expiry, WHOIS/domain expiry, DMARC policy, blacklist reputation, DNS drift. Then ask which host they run those checks against and the answer is almost always the apex: example.com. The one line item on the registrar invoice. The one row in the monitoring dashboard.
That is not attack-surface monitoring. That is monitoring one host out of dozens. And in every real-world breach the last five years has taught us, the host that got popped was almost never the apex. It was staging., legacy., marketing-2019., an abandoned Zendesk sub, or an S3 bucket a marketing intern set up in 2021 and forgot.
This piece walks the four concrete ways apex-only monitoring costs organizations real money, shows what a complete subdomain inventory looks like, and gives you a checklist you can run in one afternoon to close the gap.
Why apex-only monitoring fails
The mental model behind apex-only monitoring is that a “domain” is one thing you watch. The reality is that a registered domain is a root, and every subdomain under it can:
- Resolve to a different IP.
- Sit behind a different CDN, different origin, different cloud account.
- Carry its own SSL certificate with a different issuer and expiry date.
- Appear on IP blacklists independently of the apex.
- Have its own DNS records, security headers, and CORS configuration.
- Be delegated to an entirely different team or vendor.
Everything you monitor at the apex — SSL, headers, blacklist, HTTP status, CORS — has a per-host answer. Watching the apex tells you about the apex and nothing else. And attackers know this. The security researcher Frans Rosen has been documenting subdomain-based bug-bounty findings for the better part of a decade and the theme never changes: the apex is a fortress; the subdomains are a strip mall.
Four real ways this costs money
None of what follows is hypothetical. Every pattern below has landed in disclosure programs, post-mortems, or news cycles in the last three years.
- Subdomain takeover. A dangling
CNAMEpoints at an S3 bucket, Heroku app, Azure Blob, GitHub Pages site, or a SaaS trial that no longer exists. An attacker re-registers the target on the same platform and now serves whatever they want fromyour-brand.com/support. First-party cookies scoped to the parent domain get leaked. Phishing landing pages hosted on your brand look completely legitimate. - Expired certificate on a subdomain nobody was watching. The apex renews on schedule because it’s automated.
api-v2.example.comwas a one-off Terraform stack that a former engineer set up and the ACM auto-renewal quietly failed six weeks ago. A partner integration goes down at 2am. On-call spends four hours finding the right AWS account. - DMARC bypass via unenrolled subdomain. You set
p=rejecton the apex and called it a day. Butsp=(the subdomain policy tag) was never set, or was set tonone. Every subdomain under the apex now inherits “no policy” and an attacker sends look-alike email fromnewsletter.example.comthat passes SPF because they set up their own record on their own subdomain-of-a-subdomain. Your DMARC dashboard reports 100% aligned traffic — because the fraudulent messages aren’t going through your infrastructure at all. - IP-based blacklist listing on a subdomain your mail server lives on. The apex serves the marketing site behind Cloudflare — clean, fast, unlisted.
mail.example.comresolves to a self-hosted Postfix instance whose IP quietly ended up on Spamhaus PBL after a compromised mailbox blasted 40,000 messages. Delivery to Gmail tanks. Sales attributes the quiet week to seasonality. It takes three weeks to notice.
The subdomain takeover pattern
Subdomain takeover deserves its own section because it is the single most costly pattern in this list and the one most defenders under-weight. The mechanic is dumb-simple:
- You provision a cloud resource — S3 bucket, Heroku app, Azure Blob, GitHub Pages site, Netlify project, Vercel deployment, Zendesk portal, HelpScout Docs site.
- You point a DNS
CNAMEat it:support.example.com → yourorg.zendesk.com. - Six months later you cancel the plan or delete the resource. Nobody remembers the CNAME.
- An attacker enumerates your subdomains (using the same Certificate Transparency logs you should be reading), finds the dangling CNAME, and registers a new resource under the same name on the same platform.
- Now
support.example.comserves attacker-controlled content on your brand. Any cookie scoped to.example.comis readable. Any CSPselfallowance is exploitable. Any partner integration that trusts your subdomain is compromised.
Detectify has been publishing takeover research since 2014. Project Discovery ships an active fingerprint template list. The defensive pattern has not caught up with the offensive one. A meaningful percentage of Fortune 1000 companies have at least one dangling CNAME right now — the only question is whether an attacker or a bounty hunter finds it first.
.amazonaws.com, .herokudns.com, .azurewebsites.net, .github.io, .pages.dev, .vercel-dns.com, .netlify.app, .zendesk.com, and about a dozen more). Second, that target hostname has no A record. Together the two mean the resource is gone and the CNAME is claimable.When the “expiring cert” alert fires on the wrong host
Every serious SSL monitor watches the apex certificate. Very few watch every subdomain’s certificate. This creates a specific kind of failure: the alert you built to catch outages doesn’t fire because the outage is on a host you never told the monitor to watch.
The two most common flavours:
- Cloudflare fronts the apex, origin serves the subdomain.
example.comis proxied through Cloudflare and terminated with a Cloudflare-issued Universal SSL certificate that rotates automatically.api.example.comis served directly from an EC2 instance with a Let’s Encrypt cert that needs a working ACME challenge. The renewal silently starts failing when someone reorders the nginx location blocks. The apex monitor sees a healthy Cloudflare cert forever. - Multi-cloud, multi-issuer. Half your subdomains are on AWS ACM (auto-rotates every 13 months, no notification unless you set up EventBridge). The other half are on Let’s Encrypt (90 days, requires a working renewal cron). One of them will fail. If you’re monitoring only the apex you won’t know which one until a customer emails.
The fix is not exotic. It’s: enumerate every subdomain, subscribe your monitor to every subdomain that terminates its own TLS, and set the alert threshold to “30 days out” per host. The hard part is step one — the enumeration.
DMARC, sp=, and the subdomain-spoofing gap
Email people already know about sp=, but it’s worth stating clearly because the error is so common. DMARC has two policy tags:
p=— the policy applied to messages that use the exact apex as the RFC 5322 From domain.sp=— the policy applied to messages that use any subdomain of the apex as the From domain.
When you publish v=DMARC1; p=reject; and stop there, mailbox providers apply reject to messages claiming to be from example.com. Messages claiming to be from invoice.example.com (or secure-payments-2026.example.com, or any of the lookalike subdomains an attacker feels like inventing) fall through to whatever the mailbox provider’s local heuristic decides — usually “deliver to inbox with a soft warning at worst”. That’s a bypass.
The fix is: publish sp=reject alongside p=reject. Force strict policy on every subdomain by default. If a legitimate subdomain needs a different policy (marketing sends from mail.example.com via SendGrid), publish an override on that subdomain explicitly.
The monitoring implication is the same. If you have no inventory of your subdomains you have no way to know whether an override is missing on the ones that need it, or whether a rogue TXT record was added on one that shouldn’t have one.
How to actually find every subdomain
Subdomain discovery is a solved problem. The corpus every modern tool draws from is the same:
- Certificate Transparency logs. Every publicly-trusted certificate issued since 2018 is logged in append-only CT logs, mandated by browsers. Every SAN on every cert is a hostname somebody at your org (or a vendor of yours) provisioned. crt.sh exposes this as a free JSON API. Passive, no target-side load, no consent needed.
- DNS brute-force against a common-prefix wordlist. The top 40 prefixes (
www,api,mail,staging,admin,dev,blog,dashboard,vpn, and a few dozen more) catch roughly 80% of real-world hosts. Extended top-200 wordlists sweep the long tail — infra tiers (ns1,mx2), ops tools (grafana,sentry,jenkins), SaaS defaults (crm,billing,hr). - Passive DNS data. Commercial services like SecurityTrails, VirusTotal, and DNSDB carry historical resolutions from real user queries. Catches subdomains that never issued a cert and aren’t in your brute-force wordlist. Useful for the last 5–10%.
Combining the first two sources catches almost every subdomain that matters. The CLI tools (Sublist3r, Subfinder, Amass, Assetfinder) all combine them differently. The hosted tool below does it in one call with liveness enrichment (DNS, HTTP, TLS cert per host) and a takeover-risk cross-check on every CNAME — the same information you’d get from Amass plus subzy plus httpx plus tlsx, without setting anything up.
Monitoring that scales with your subdomains
Finding subdomains is one problem. Monitoring every one of them continuously is a different problem, and it’s where DIY setups fall apart. Once you have 30 subdomains you need per-host cert expiry alerts, per-host header audits, per-host blacklist checks, per-host CNAME drift tracking, and a way to be told the second a new subdomain appears in a CT log that nobody on your team requested.
That last one is the load-bearing signal. In real breaches the sequence is: attacker registers a lookalike CNAME under your apex, gets a certificate for it (necessarily logged to CT), sets up the harvest page, then blasts phishing links. If you were watching the CT logs you would have seen the certificate issuance minutes after the fact. Most defenders don’t watch it.
DomainScan’s platform tier turns this on by default. Every apex you onboard triggers a subdomain discovery run. Every discovered host shows up in a Discovered queue you can promote to Monitored in one click. Every monitored host runs the full SSL / blacklist / header pipeline against its own hostname. The platform re-runs subdomain enumeration every 24 hours and fires a NEW_SUBDOMAIN alert the moment a host appears that wasn’t there yesterday — including CT-only hosts you didn’t provision.
A checklist for this week
Every item on this list is something you can finish inside two hours if you already know your DNS.
- Enumerate. Point a subdomain finder at every apex your org owns. Save the output. Don’t stop at your primary brand — the -shop.com, -corp.io, -mobile.app and other spelling variants your marketing team registered five years ago all count.
- Triage the dead ones. Hosts that don’t resolve today but appear in CT are old infrastructure. Verify the CNAME is dead-dead (not just intermittent). If the target matches a cloud fingerprint and doesn’t resolve, that’s a takeover-risk row. Remove the CNAME the same day.
- Inventory the live ones. Group by ownership. Every subdomain has an owner — the team that provisioned it, the vendor it’s delegated to, the CDN it fronts. Write it down.
- Verify TLS per host. Every live subdomain that terminates its own TLS needs its own 30-day-out alert. Cloudflare-fronted hosts inherit the front-door cert; origin-terminated hosts do not.
- Publish
sp=reject. If your DMARC record isp=reject; sp=none;or has nosp=at all, you have a subdomain-spoofing gap. Fix it. - Set up new-subdomain alerts. Whether you build it yourself (poll crt.sh nightly and diff) or use a platform, the signal “a cert appeared for a hostname I don’t remember provisioning” is one of the highest-value security signals available.
- Repeat monthly for the first quarter. The first pass catches the biggest gaps. The second and third catch what the first missed. After 90 days you’ll have a real inventory.
FAQ
How is this different from an EDR / EASM tool like Randori or CyCognito?
Enterprise EASM is broader in scope (cloud metadata scraping, port scanning, config drift across inventory) and orders of magnitude more expensive. It’s the right tool for a security organization with a dedicated program. If your team is one person part-time and you just need to stop losing time to expired certificates on subdomains you forgot existed, the subdomain finder plus per-host monitoring is 90% of the value for 5% of the cost.
Do I need to authenticate to enumerate my own subdomains?
No. Certificate Transparency is public by design — the whole point of CT is that browsers can verify certs against a public log. crt.sh is a free interface to that log. DNS brute-force sends one query per candidate hostname and the target sees only the queries that actually resolve. You don’t need to be logged in as the domain owner to check your own attack surface — but you also don’t need to be logged in to check anyone else’s, which is exactly why doing it yourself is the responsible move.
What if my subdomain uses a wildcard cert?
Wildcards mean the certificate itself doesn’t tell CT what hostnames are actually in use. Passive CT still catches subdomains that get their own non-wildcard certs (most modern infra does), and DNS brute-force catches the rest. Wildcards make discovery harder, they don’t make it impossible.
How often do subdomains actually change?
In an active engineering org: multiple new subdomains a week from staging environments, feature branches, review apps, and preview deployments. In a stable org: one or two a month from marketing campaigns and SaaS onboarding. Either way, the delta between “what we thought we had” and “what actually exists” grows month over month unless something is actively closing the gap.
Isn’t crt.sh sometimes down?
Occasionally, yes. Under load crt.sh can time out or return partial results. Any serious tool should fall back to DNS brute-force when passive CT fails, and should not cache empty results. That’s a good filter question when you’re evaluating options.