Subdomain Takeover Detection
A dangling subdomain — one still pointing at a service you've since torn down — is an open door: anyone can re-register that service and speak as you. This walks a domain's subdomains and flags the ones aiming at deprovisioned targets, so you can reclaim or remove them before someone else does.
The alert
An attack-surface sweep of github.com returns a subdomain whose CNAME points at github.github.io, and the graph shows no address behind that target. That is the takeover signature: a name still delegated to a service that answers for nobody, so whoever claims the service speaks as you — Dangling DNS record.
The question
Do I open a takeover ticket on this subdomain, and what would tell me I am wrong?
Not "is this CNAME dangling". The run answers that, and on this estate the answer it gives is mostly an artefact of how one address got stored.
What this cannot answer
- Whether the target is claimable. Confirming a takeover means attempting the registration against the provider that owns the target's zone. That is an active step taken outside the graph, and no query substitutes for it.
- Whether the target really fails to resolve. A missing
RESOLVES_TOis an absent observation, not NXDOMAIN. Hostnames served only through private or split-horizon resolvers carry none at all — Known Limitations. - Whether the estate is complete. 40,916 hostnames sit under
github.com, measured 2026-08-09. That is what has been observed, not what exists; a subdomain nobody ever published is one this run never sees. - How stale the delegation is.
ALIAS_OFrecords a CNAME that was seen. Nothing on the edge says it is still being served.
What do we know
Of those 40,916 hostnames, 141 carry an ALIAS_OF edge — 207 edges onto 24 distinct targets. 57 of the 207 land on a target with no IPV4 behind it, and that is the shape the run reports as dangling.
whisper.assess on the four targets that survive the check below returns clean, band NONE, coverage known-clean on all four. That is a populated row saying the threat plane holds nothing about them, not an empty result: zero rows is never a verdict. It is also the correct answer to the wrong question. Takeover is about who can claim a name, and no feed lists a target before somebody abuses it — read the qualifier first, on Coverage.
Two sampling facts belong here rather than in a footnote, because they decide what an empty section means. The estate step reads the first fifty names alphabetically; on this seed all fifty are legacy user pages like 0.github.com, and not one carries an address or a CNAME. The chain step samples two hundred subdomains and returned 0 rows on three consecutive runs — 141 hostnames of 40,916 carry a CNAME, so an unordered two-hundred sample is expected to contain none. Anchoring the same query on WHERE (s)-[:ALIAS_OF]->() returns 50 rows. An empty chain section is that sample missing, never an estate without CNAMEs.
Why
- 01Subdomain estate. The estate is the candidate set for dangling references.
- 02Dangling CNAMEs. A CNAME to a non-resolving target is the takeover signature (prod-ahead ALIAS_OF layer).
- 03CNAME delegation chains. Traces each subdomain's full CNAME delegation chain (up to 5 hops) and flags chains whose final target no longer resolves to an IP — the dangling endpoint a takeover would hijack.
The pivot the score did not suggest
The run emits one boolean per edge and 57 of them are true. Sort those 57 by where the target's own name lives — CHILD_OF gives the parent zone — and they stop looking alike. 53 point back into GitHub's namespace, 50 of them at the single node github.github.io. Four point off-estate: 157-gqe-382.mktoweb.com, communication.github.com.cname.campaign.adobe.com, porter-production-1232719825.us-east-1.elb.amazonaws.com and mailgun.org.
Only off-estate targets are takeover-shaped, because a takeover needs a registration counter somebody else operates. A name in a zone you already control is not a name a stranger can claim. The boolean discarded the zone, and the zone is where the whole risk sits.
Falsify it
Drop the :IPV4 label from the resolution test. That one edit takes 57 flags to 4.
github.github.io has no RESOLVES_TO edge to any :IPV4 node. It has three to nodes labelled HOSTNAME and named 185.199.109.153, 185.199.110.153 and 185.199.111.153, plus one to an :IPV6. An :IPV4 node named 185.199.109.153 also exists and is resolved to by 307,984 hostnames; this target's A records did not land on it. The other three that fall away are cli.github.io, pages.github.com and mailgun.org — mailgun.org resolves to two :PREFIX nodes, so it fails an :IPV4 test while answering perfectly well.
The CNAME and namespace patterns, runnable with their measured output, are on Pentest and recon recipes.
The conclusion
On github.com this run produces four candidates, not 57, and three are worth a ticket: info.github.com into mktoweb.com, communication.github.com into an Adobe Campaign zone, importer2.github.com into a us-east-1.elb.amazonaws.com name. Each is a delegation into somebody else's registration namespace with nothing observed behind it. media.github.com into alambic-origin.github.com stays inside GitHub and is hygiene, not exposure.
Nothing here says any of the three is claimable. Four findings would overturn the ticket, and each is a check rather than an opinion:
- the target answering an active lookup, which this graph does not perform;
- the provider refusing re-registration of a released name, which is provider policy and not a graph fact;
- a
RESOLVES_TOedge appearing on a later run, since these edges follow observation and observation churns; - the
ALIAS_OFedge proving stale, which the edge itself cannot tell you.
The first three cost a probe and an email. Shipping all 57 costs a week of somebody's attention, and 53 of them were a label.
What this cost
3 named steps across the DNS layer. The runner reports what each step returned, row by row, so the evidence and what it took to get it arrive together rather than as one number at the end.
How it uses the graph
Traverses the DNS layer of the graph, in 3 steps:
Enumerating the subdomain estate…
Flagging CNAMEs whose target no longer resolves…
CNAME delegation chains…