Skip to contentSkip navigation

Entities

Every node label in WhisperGraph — what it represents, its count, and the queryable properties on threat-listed indicators, prefixes, ASNs, and ROAs.

Graph Schema
On this page (16)

Entities Documentation

Every entity in WhisperGraph is a node with a label and a name. This page lists every node label the engine returns — what each represents, how many exist, whether it is joinable at all, and the properties you can filter and return. For the edges that join them, see Connection Types; for the chains that cross layers, see Pivoting Examples.

There is no Domain or FQDN label — every name is a HOSTNAME. The table below is generated: its rows are whatever CALL db.labels() returned when the census last ran, and its counts resolve at render from that same census. A label the engine adds appears here without anyone typing it, and a label the engine drops leaves.

The Edge types column is the number of edge types that name the label as a source or a target in CALL db.relationshipTypes(). Read it as declared, not as reachable: CATEGORY shows zero and yet (f:FEED_SOURCE)-[:BELONGS_TO]->(c:CATEGORY) returns rows, because BELONGS_TO carries that hop without declaring it. A zero is a reason to check, and three of them — RDAP_ENTITY, DNS_ROOT_INSTANCE and DWI_DOMAIN — were checked by expanding an anchored node in both directions on 2026-08-09 and hold zero edges of any type. They list; the traversal cannot be written.

Node labels

Core DNS & addressing

LabelRowsEdge typesWhat it is
HOSTNAME2,729,827,27225A fully qualified domain name (google.com, mail.google.com).
IPV4621,048,45613An IPv4 address.
IPV66,024,94410An IPv6 address.
PREFIX2,493,4119A CIDR block an IP belongs to.
ANNOUNCED_PREFIX1,423,4384A prefix actually announced in BGP.
REGISTERED_PREFIX331,0201A prefix allocated by a regional registry.
TLD3,1382A top-level domain (com, nissan).

Routing & organization

LabelRowsEdge typesWhat it is
ASN116,02813An autonomous system, named AS + number (AS13335).
ASN_NAME107,7201The registered name of an autonomous system.
ORGANIZATION119,189,8473A registrant or network organization. Names are stored lowercase — see the anchoring note below.
RIR50A regional internet registry.
TLD_OPERATOR7371A registry that operates one or more TLDs.

WHOIS & registration

LabelRowsEdge typesWhat it is
REGISTRAR50,6602A domain registrar.
EMAIL237,065,6632A WHOIS contact email.
PHONE60,194,1422A WHOIS contact phone.
RDAP_ENTITY370,0850An RDAP deep-WHOIS registration entity. Carries no edges — reach registration data through EMAIL, PHONE, REGISTRAR and ORGANIZATION.

Geo & DNSSEC

LabelRowsEdge typesWhat it is
CITY54,2332A GeoIP city (New York, US).
COUNTRY4241A country.
DNSSEC_ALGORITHM80A DNSSEC signing algorithm.

Threat intelligence

LabelRowsEdge typesWhat it is
FEED_SOURCE761A threat-intelligence feed. Anchor on the wire name (abuse-ch-feodo-tracker), not the display label.
CATEGORY310A threat or reference category. The name is a lowercase slug (c2, phishing, blacklists). Reached from a feed over BELONGS_TO, which the introspection call does not declare — see the note below.
THREAT_TAG12,7302A MISP-galaxy threat tag, reached over TAGGED_AS.
THREAT_SIGNAL_TYPE111A threat-signal taxonomy entry (bulletproof-hosting, c2-hosting).
ACTOR1,2182A named threat actor (APT28). Case-sensitive.
ATTACK_PATTERN7122A MITRE ATT&CK technique or tactic.
DWI_DOMAIN170A dark-web domain under watch (.onion), carrying its own dwi_* properties and a verdict. No edge type reaches it.

RPKI & routing observations

LabelRowsEdge typesWhat it is
ROA3,255,1612An RPKI Route Origin Authorization. It has no name — identify it by prefix and asn.
BGP_PATH_OBSERVATION7,980,1711An observed AS-path, reached over BGP_PATH.

Physical infrastructure

LabelRowsEdge typesWhat it is
FACILITY5,8615A datacenter or carrier-hotel building (Equinix DA1 - Dallas).
INTERNET_EXCHANGE1,3182An internet exchange point (LINX LON1).
SUBMARINE_CABLE6971A subsea cable (2Africa).
CABLE_LANDING1,9222A landing point for a subsea cable.
CDN_POP1,6771A CDN point of presence (operator-prefixed id).
DNS_ROOT_INSTANCE1,5340A root-server instance. The nodes list; nothing joins to them.
CLOUD_REGION911A cloud-provider region (aws:eu-west-1). Only 3,288 prefixes are mapped to one.

Egress, fingerprint & transparency

LabelRowsEdge typesWhat it is
VENDOR532A cloud or SaaS vendor that operates address space (cloudflare).
TOR_RELAY3,1911A Tor relay, keyed by fingerprint.
TLS_FINGERPRINT7651A JA3 or JARM TLS fingerprint. Only 261 IPs graph-wide emit one.
CT_OBSERVATION29,7641A Certificate Transparency observation, against 2.7B hostnames. github.com has none; paypal.com has none.
DMARC_RECIPIENT36,1191An address a domain sends DMARC reports to.

Rows generated from CALL db.labels() YIELD label, count against https://graph.whisper.security, fetched 2026-08-09T21:11:53Z. The counts render from that same census, so a replica disagreeing by a few million moves the number without moving the table.

Most node labels carry an indexed name, and {name: "value"} lookups hit that index. ROA does not — identify a ROA by the prefix and ASN it authorizes. FEED_SOURCE, CATEGORY, ANNOUNCED_PREFIX, and REGISTERED_PREFIX are virtual labels synthesized at query time. The small ones (FEED_SOURCE, CATEGORY) can be listed directly; reach the prefix labels through an edge (ANNOUNCED_BY, BELONGS_TO) rather than scanning them.

Do not anchor on an organization's display name. ORGANIZATION names are stored normalized and lowercase, so the string on a WHOIS record is not the key. Measured 2026-08-09 against production: {name: "Cloudflare, Inc."} returns zero rows at HTTP 200 with no error, while {name: "stripe"} — the stored form — returns its row in 4 ms. Reach an organisation through an edge first (REGISTERED_BY from a hostname, IP or ASN), read the name off that row, and use that as your anchor. A zero-row result on an ORGANIZATION name lookup is almost always the casing, not an absence of data.

Three labels are listable but unjoinable, and the difference matters before you write the query. RDAP_ENTITY, DNS_ROOT_INSTANCE and DWI_DOMAIN hold no edge of any type — by expanding an anchored node in both directions, and confirmed against the generated connection census, in which no edge type reaches any of the three. They can be counted and read property by property; the traversal into or out of them cannot be written at all. BGP_PATH_OBSERVATION is not in this group: it is reached over BGP_PATH.

Node properties

Most labels carry only name. Threat-listed indicators, announced prefixes, ASNs, and ROAs carry richer, queryable properties.

Read coverage before band. Only known-clean — coverage: known-clean. In coverage, no malicious evidence. licenses the word "clean"; no-data — coverage: no-data. Not in coverage. This is not a verdict — nothing was looked at. means unknown, which is a different thing again; malicious-evidenced — coverage: malicious-evidenced. In coverage, with positive evidence of malice. and ambiguous — coverage: ambiguous. In coverage, and the evidence points both ways. mean there is evidence, whatever the band says. whisper.explain does not return coverage at all. Full contract: Coverage — what we looked at.

Threat & verdict (on threat-listed IPV4 / IPV6 / HOSTNAME)

PropertyTypeNotes
verdictScoreDoubleReconciled triage score — prefer this over threatScore.
verdictLevelStringReconciled level: NONECRITICAL.
verdictBlockingBooleanWhether the reconciled verdict recommends blocking.
verdictCoverageStringWhat Whisper actually looked at, which is a different question from how bad it is. Read it alongside verdictLevel, never instead of it.
verdictAdvisoryStringA short reason string when one applies (allowlist-vouched, dwi-monitored-cybercrime). Frequently null, including on listed indicators — — so treat a null as no advisory, not as an error.
threatScoreDoubleRaw feed-weighted score. Never clamped, so it keeps the full feed evidence.
threatLevelStringNONE / INFO / LOW / MEDIUM / HIGH / CRITICAL.
threatSourcesIntegerThe number of feeds that flagged the indicator — not their names. WHERE "greensnow" IN ip.threatSources matches nothing. The names come from the LISTED_IN traversal, or from explain()'s sources[].
threatFirstSeen / threatLastSeenepoch msFirst/last time the indicator was seen on a feed.

Boolean flags — 20 of them, measured on a listed node on 2026-08-09: isThreat, isAnonymizer, isC2, isMalware, isPhishing, isSpam, isBruteforce, isScanner, isBlacklist, isTor, isProxy, isVpn, isWhitelist, isReputation, isBotnet, isDga, isStateActor, isExfilDestination, isOfacSanctioned, isScam.

Curated well-known infrastructure (public resolvers like 8.8.8.8) carries an allowlisted flag, and its verdict surfaces (verdictLevel, threatLevel, isThreat) are clamped to benign. The raw threatScore is never clamped, so WHERE ip.threatScore > 5 still matches an allowlisted resolver.

cypher · runnablegraph.whisper.securitySign in to run
// Triage an IP on the reconciled verdict (preferred over raw threatScore)
MATCH (ip:IPV4 {name: "185.220.101.1"})
RETURN ip.name, ip.verdictScore, ip.verdictLevel, ip.verdictBlocking, ip.isTor, ip.isAnonymizer
LIMIT 1

BGP enrichment (on ANNOUNCED_PREFIX)

PropertyTypeNotes
isMoasBooleanCurrently announced by more than one origin AS (MOAS).
isAnycastBooleanAnnounced from multiple locations.
isWithdrawnBooleanCurrently withdrawn from the routing table.
threatScore / threatLevel / threatSourcesDouble / String / IntegerAggregate threat across the prefix. threatSources is a count of feeds here too, not a list of names.
rirStringThe allocating regional registry.
registrationDate / lastChangedDatedateAllocation and last-change dates.

ASN aggregate threat (on ASN)

PropertyTypeNotes
maxThreatScore / avgThreatScoreDoubleMax / average threat across the AS's routed prefixes.
overallThreatLevelStringRolled-up level for the AS.
hasThreateningPrefixesBooleanWhether any routed prefix is threat-listed.
rirStringThe allocating regional registry.
registrationDate / lastChangedDatedateAllocation and last-change dates.

RPKI (on ROA)

A ROA has no name. Its identity is the pair prefix + asn, and that is what you select and filter on.

PropertyTypeNotes
prefixStringThe prefix the ROA authorizes (1.1.1.0/24). Half of the ROA's identity.
asnIntThe authorized origin AS as a bare number (13335), not the AS13335 string form used to anchor an ASN node.
maxLengthIntMaximum prefix length the ROA authorizes.
authSourceStringrpki-roa — the only value, across every ROA sampled on AS13335, AS3356 and AS8075. Filter on rpki-roa; do not filter for an irr value.
trustAnchorStringThe RPKI trust anchor (apnic, ripe).
validFrom / validUntiltimestampROA validity window.

Other enriched labels

LabelNotable properties
TOR_RELAYname (fingerprint), fingerprint, exitAddressCount, source.
CT_OBSERVATIONname (the observed cert name), certCount, firstSeen, lastSeen, wildcard.
VENDORname (lowercase slug), displayName, category (cdn on cloudflare), confidence, aliases.
TLS_FINGERPRINTname (jarm:/ja3:-prefixed hash), hash, kind, family. firstSeen, lastSeen and sourceCount exist but read -1, -1 and 0 on every fingerprint sampled on 2026-08-09 — do not filter on them.
THREAT_SIGNAL_TYPEname — one of 11 signal kinds, e.g. bulletproof-hosting, c2-hosting, toxic-neighborhood, coordinated-campaign.

LISTED_IN edges carry no queryable properties. The per-feed evidence behind a verdict (each feed's weight and first/last-seen timestamps) comes from explain(), which returns it as an inspectable sources array.

Confirm a label before you anchor

cypher · runnablegraph.whisper.securitySign in to run
CALL db.labels() YIELD label RETURN label ORDER BY label

db.labels() lists every node label with its count, and it answers immediately. Checking it first is the fastest cure for the most common mistake — anchoring on a label that doesn't exist and getting silent empty results.

CALL db.propertyKeys() and CALL db.schema.nodeTypeProperties() show the live property set, but use them to discover, not to enumerate: nodeTypeProperties() under-reports. Measured 2026-08-09, it lists 8 of IPV4's 20 boolean flags, and nothing beyond name / label / nodeId for TOR_RELAY, TLS_FINGERPRINT, CT_OBSERVATION, VENDOR and ROA — including for ROA, which does not carry a name at all. When you need the full set for one node, return the node itself and read the keys off the response.