Skip to contentSkip navigation

Takedown Evidence Package

When you've found a malicious domain, the next hurdle is proving it. This assembles a one-pass takedown package — the reputation verdict, who owns it, the abuse lists naming it, and the infrastructure around it — laid out ready to hand to a registrar or hosting provider so the takedown actually sticks.

The alert

A customer forwards a link and the host in it is ickaoex.com. explain() scores the domain 46.07 / HIGH — enough to open a case, nothing like enough to make a registrar close it.

The question

Do I file a takedown on this domain, and what would tell me I am wrong?

A score ranks the domain. A complaint has to name somebody accountable, and nothing in 46.07 / HIGH names anyone.

What this cannot answer

  • What is on the page. Whisper reads infrastructure, never content. whisper.assess returns the sub-label malware because a feed classified it that way; nothing in this run fetched the site. The screenshot the abuse form asks for has to come from you.
  • Who registered it. The WHOIS step returns nothing on this domain — run twice on 2026-08-09, and each of its four branches run separately. whisper.history covers part of the gap and hands back REDACTED FOR PRIVACY for the registrant.
  • Where the site is served from. Both addresses the run finds are Cloudflare edge addresses. The origin is not in the graph, so the hosting half of a takedown has no addressee here.
  • How current the registration record is. The stored WHOIS snapshot carries queryTime 2026-04-09 16:48:01, three days after the domain was created, and unmoved since.
  • How much of the domain was actually checked. That is the coverage qualifier on whisper.assess, and reading it comes first — Coverage.

What do we know

whisper.assess(["ickaoex.com"]) returns label: malicious, band: HIGH, sub_labels: ["malware"], and the qualifier that decides how hard you can push: coverage: malicious-evidenced, with host-class:unknown and feed-source-count:1 in its evidence array.

One source. The whole threat case is hagezi-tif-full, weight 1.50, first seen 2026-08-03, last seen 2026-08-07. explain() prints the arithmetic that turns that into a number: base 1.50 × log₂(1 + 1) = 40.00, then a recency multiplier and an age multiplier.

Which is why the dossier carries two numbers for one domain. The feed step returns the stored threatScore of 40.00; explain() returns 46.07. Those are the same score before and after the multipliers: put the arithmetic in the package, not the bare figure.

The empty WHOIS result is not a finding about the domain: zero rows is never a verdict. Here the four branches were re-run one at a time and the domain's outgoing edges enumerated — RESOLVES_TO, LISTED_IN, CHILD_OF, no registration edge. The absence survived that check, which is what makes it reportable.

Why

  1. 01Threat verdict. Opens the dossier with the authoritative sourced verdict that justifies pursuing a takedown at all.
  2. 02Threat-feed listings. Cites the specific LISTED_IN feeds (minus popularity lists) plus the score and level — third-party corroboration a registrar/host will accept.
  3. 03WHOIS owner, registrar & contact. Names the registrar and registrant organisation — the accountable parties and the addressees of an abuse complaint.
  4. 04Registration age (NRD signal). Surfaces creation date via whisper.history; a newly-registered domain is a strong abuse indicator that strengthens the case.
  5. 05Resolving IPs + network owner. Maps the domain to its IP, prefix and named ASN, identifying the host that abuse contact must also reach.
  6. 06Co-hosted domains (the wider campaign). Reverse-resolves the IP to surface co-hosted siblings — the wider campaign that should be taken down alongside the seed.
  7. 07Registered look-alikes. Lists existing brand variants so related squats are bundled into the same takedown rather than left to resurface.

The pivot the score did not suggest

Follow the two addresses one step further, which is what the hosting step does. 104.21.77.231 sits in 104.21.64.0/20, 172.67.212.145 in 172.67.208.0/20, and both prefixes are routed by AS13335 — CLOUDFLARENET. The two inbound NAMESERVER_FOR edges name bethany.ns.cloudflare.com and boyd.ns.cloudflare.com. Naming and transport are both proxied, so the "network owner" the run produces is a reverse proxy rather than a host.

The co-hosted step inherits that. 2091 hostnames resolve to 104.21.77.231, and 23 of them carry any feed listing at all. On a dedicated address that step finds a campaign; on a shared edge address it finds tenants — spaceify.ai, radarcovid.app, a chiropractor in South Australia.

The score contains no hint of either fact. The one accountable party the whole run produces arrives from whisper.history: registrar West263 International Limited, registrant country SG, created 2026-04-06.

Falsify it

The case rests on a single listing, so re-run the feed step before sending anything. If hagezi-tif-full drops the domain, explain() returns 0.00 / NONE and the package is empty — which is exactly what it returns today for the one look-alike this run found.

That look-alike repays a second query. whisper.variants returns one existing variant, yckaoex.com, method BITSQUATTING, confidence 1.0. It scores 0.00 / NONE and has no RESOLVES_TO edge, yet it carries the owner record the seed lacks: registrant privacy service provided by withheld for privacy ehf, plus a WHOIS phone and email. Note what its registrar field returns — iana:1068. The REGISTRAR node holds an IANA identifier, so even the working version of that step hands you a number to look up rather than a name.

Nothing in the graph joins yckaoex.com to ickaoex.com beyond the string. Bundling it into the same complaint is an assertion this run does not support. The queries, with their output, are on Threat intel.

The conclusion

ickaoex.com is filable at the registrar and nowhere else: one feed listing classified as malware, a registration dated 2026-04-06 through West263 International Limited, a redacted registrant, and every hosting-side addressee resolving to a reverse proxy. Address it to the registrar whisper.history names. Addressing it to AS13335 names a company that is not serving the content.

Four things would change that, and each is a query rather than an opinion:

  • the feed step returning nothing on a later run — the entire threat case is one listing, and listings churn;
  • a HAS_REGISTRAR or REGISTERED_BY edge appearing on the domain, which would give the package an owner it does not have today;
  • a co-hosted sibling that shares the registrar or the registrant rather than only the address, which would turn 2091 neighbours into a campaign;
  • yckaoex.com starting to resolve, which would make the look-alike a second target instead of a footnote.

A registrar can check a dossier that says which of its claims are queries. It cannot check one that says HIGH.

What this cost

7 named steps across the threat-intel, DNS, WHOIS layers. 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 threat-intel, DNS, WHOIS layers of the graph, in 7 steps:

How it walks the graph7 steps
01Threat verdict

Scoring the domain with explain()…

threat-intelDNSWHOIS
02Threat-feed listings

Listing the threat feeds that name it…

threat-intelDNSWHOIS
03WHOIS owner, registrar & contact

Reading the WHOIS registrar and registrant…

threat-intelDNSWHOIS
04Registration age (NRD signal)

Pulling registration history for the NRD signal…

threat-intelDNSWHOIS
05Resolving IPs + network owner

Resolving IPs and naming the hosting network…

threat-intelDNSWHOIS
06Co-hosted domains (the wider campaign)

Finding domains sharing its IP…

threat-intelDNSWHOIS
07Registered look-alikes

Generating registered look-alike domains…

threat-intelDNSWHOIS