whisper.origins() — Origin Discovery

De-cloak a CDN-fronted domain to its real origin IPs, ranked by confidence and how they were found.

Updated July 2026Procedures

whisper.origins() — Origin Discovery Documentation

whisper.origins() finds the real origin IPs behind a CDN or proxy. When a target sits behind Cloudflare, a scanner only sees the CDN edge. The origin servers still leak into passive data — the addresses a domain's mail, SPF, and sibling hostnames point at, around the proxy — and this procedure collects those signals and ranks each candidate by how much corroborating evidence backs it.

It is a passive lookup. No packet ever touches the target. Every candidate comes from records already in the graph, so you can run it against a domain you have no permission to scan.

Call it from Cypher with CALL. It takes a domain and returns candidate origin IPs, each with a confidence score, the methods that found it, and the ASN it lives on. Highest confidence comes first.

Signature and returns

CALL whisper.origins("cloudflare.com")
YIELD ip, confidence, methods, asnName
WHERE confidence >= 8
RETURN ip, confidence, methods, asnName
ORDER BY confidence DESC
LIMIT 10

Each row carries:

FieldMeaning
ipA candidate origin IPv4 address.
confidenceA score; higher means more corroboration. Filter on confidence >= 8 to keep the strong, web-origin candidates.
methodsHow the IP was found: mx, spf, sibling, or a leaked web link.
asnName / asnThe network the IP lives on.
kind"origin" for a default-grade candidate, "related" for opt-in CDN/shared context.
categorynull for a plain origin, "vpsh" for a labelled VPS origin, or the withhold reason ("cdn" / "anycast" / "shared_provider") on a related row.
truncatedtrue when a discovery arm hit its per-query cap on a large estate and returned a bounded partial result.

The short YIELD ip, confidence, methods, asnName form keeps working unchanged; kind, category, and truncated are additive.

How candidates are found

methods tells you which signal surfaced each IP:

  • mx — the address of a mail server for the domain.
  • spf — an address authorized to send mail in the domain's SPF record.
  • sibling — a co-located host in the same registrable domain (the PSL eTLD+1).
  • a leaked web link — the domain links out to an address that sits behind the proxy.

The strongest signal is corroboration. An IP found by more than one method — say mx and a sibling host — scores highest, because several independent records agree on it. A single mail-only finding is the weakest signal: third-party mail providers (Google Workspace, Microsoft 365, SendGrid, Mailgun) serve mail for thousands of unrelated domains, so those addresses are shared infrastructure, not the target's web origin. The procedure down-weights mail and SPF IPs that resolve to a known shared-mail provider's network and caps any mail-only candidate below the high-confidence band. Those IPs still appear at low confidence with methods: ["mx"]; they just can't bury a corroborated web origin. Filtering on confidence >= 8 keeps the corroborated candidates and drops the lone-mail noise.

Sibling, MX, and SPF discovery are anchored at the target and its registrable apex, so whisper.origins("example.com") and whisper.origins("www.example.com") return the same origins, and a tenant query like whisper.origins("foo.github.io") stays scoped to *.foo.github.io and never picks up the platform operator's infrastructure.

When it works, and when it does not

Origins works when a domain fronted by a CDN still leaks its origin through mail, SPF, sibling hosts, or web links. That covers most real-world estates: mail rarely runs through the CDN, and SPF records name the sending IPs directly.

It returns nothing useful when:

  • The input has no registrable anchor — a public suffix like github.io, a bare IP literal, or an unknown TLD. The sibling, MX, and SPF arms contribute no rows.
  • The domain runs mail and web entirely through the same proxy with no leaked side channel.
  • The estate is so large that the discovery arms hit their per-query cap. When that happens the truncated flag comes back true, which is your cue to narrow the target rather than treat the result as complete.

By default the procedure returns origin-grade candidates only. An IP whose covering ASN is CDN or anycast infrastructure and that was found only through the weak web-link arm is withheld — it is contextual infrastructure the target merely links to, not its origin. An organization that runs its own anycast or CDN network keeps its rows, and a VPS or shared-hosting IP is kept and labelled (category: "vpsh"), since a VPS is often the genuine origin of a small site. To include the withheld CDN and shared-provider context, pass the options map:

CALL whisper.origins("cloudflare.com", {include_related: true})
YIELD ip, confidence, methods, asnName, kind, category
RETURN ip, confidence, methods, asnName, kind, category
ORDER BY kind, confidence DESC
LIMIT 20

Related rows always sort below the genuine origins.

Pivot from an origin

An origin IP is a starting point, not a verdict. Once you have one, pivot it through explain() for a threat read, or check its listings and network directly:

CALL explain("104.18.7.42")
YIELD indicator, score, level, sources
RETURN indicator, score, level, sources

Run it live

The Find the real infrastructure behind the CDN workflow runs this de-cloak end to end and corroborates each origin against Certificate Transparency. The broader Attack Surface & Recon use case combines origins with subdomain, mail, and hosting enumeration to map an org's full external footprint.

whisper.origins() runs on the anonymous tier, but the deeper cross-layer follow-ups pair best with a free key. Sign in to raise the anonymous 2-hop cap to 3 hops and lift the rate limit. See the procedures overview for the full set and best practices for the rules that keep queries fast.