Entities
Every node label in WhisperGraph — what it represents, its count, and the queryable properties on threat-listed indicators, prefixes, ASNs, and ROAs.
On this page (16)
- Node labels
- Core DNS & addressing
- Routing & organization
- WHOIS & registration
- Geo & DNSSEC
- Threat intelligence
- RPKI & routing observations
- Physical infrastructure
- Egress, fingerprint & transparency
- Node properties
- Threat & verdict (on threat-listed IPV4 / IPV6 / HOSTNAME)
- BGP enrichment (on ANNOUNCED_PREFIX)
- ASN aggregate threat (on ASN)
- RPKI (on ROA)
- Other enriched labels
- Confirm a label before you anchor
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
| Label | Rows | Edge types | What it is |
|---|---|---|---|
HOSTNAME | 2,729,827,272 | 25 | A fully qualified domain name (google.com, mail.google.com). |
IPV4 | 621,048,456 | 13 | An IPv4 address. |
IPV6 | 6,024,944 | 10 | An IPv6 address. |
PREFIX | 2,493,411 | 9 | A CIDR block an IP belongs to. |
ANNOUNCED_PREFIX | 1,423,438 | 4 | A prefix actually announced in BGP. |
REGISTERED_PREFIX | 331,020 | 1 | A prefix allocated by a regional registry. |
TLD | 3,138 | 2 | A top-level domain (com, nissan). |
Routing & organization
| Label | Rows | Edge types | What it is |
|---|---|---|---|
ASN | 116,028 | 13 | An autonomous system, named AS + number (AS13335). |
ASN_NAME | 107,720 | 1 | The registered name of an autonomous system. |
ORGANIZATION | 119,189,847 | 3 | A registrant or network organization. Names are stored lowercase — see the anchoring note below. |
RIR | 5 | 0 | A regional internet registry. |
TLD_OPERATOR | 737 | 1 | A registry that operates one or more TLDs. |
WHOIS & registration
| Label | Rows | Edge types | What it is |
|---|---|---|---|
REGISTRAR | 50,660 | 2 | A domain registrar. |
EMAIL | 237,065,663 | 2 | A WHOIS contact email. |
PHONE | 60,194,142 | 2 | A WHOIS contact phone. |
RDAP_ENTITY | 370,085 | 0 | An RDAP deep-WHOIS registration entity. Carries no edges — reach registration data through EMAIL, PHONE, REGISTRAR and ORGANIZATION. |
Geo & DNSSEC
| Label | Rows | Edge types | What it is |
|---|---|---|---|
CITY | 54,233 | 2 | A GeoIP city (New York, US). |
COUNTRY | 424 | 1 | A country. |
DNSSEC_ALGORITHM | 8 | 0 | A DNSSEC signing algorithm. |
Threat intelligence
| Label | Rows | Edge types | What it is |
|---|---|---|---|
FEED_SOURCE | 76 | 1 | A threat-intelligence feed. Anchor on the wire name (abuse-ch-feodo-tracker), not the display label. |
CATEGORY | 31 | 0 | A 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_TAG | 12,730 | 2 | A MISP-galaxy threat tag, reached over TAGGED_AS. |
THREAT_SIGNAL_TYPE | 11 | 1 | A threat-signal taxonomy entry (bulletproof-hosting, c2-hosting). |
ACTOR | 1,218 | 2 | A named threat actor (APT28). Case-sensitive. |
ATTACK_PATTERN | 712 | 2 | A MITRE ATT&CK technique or tactic. |
DWI_DOMAIN | 17 | 0 | A dark-web domain under watch (.onion), carrying its own dwi_* properties and a verdict. No edge type reaches it. |
RPKI & routing observations
| Label | Rows | Edge types | What it is |
|---|---|---|---|
ROA | 3,255,161 | 2 | An RPKI Route Origin Authorization. It has no name — identify it by prefix and asn. |
BGP_PATH_OBSERVATION | 7,980,171 | 1 | An observed AS-path, reached over BGP_PATH. |
Physical infrastructure
| Label | Rows | Edge types | What it is |
|---|---|---|---|
FACILITY | 5,861 | 5 | A datacenter or carrier-hotel building (Equinix DA1 - Dallas). |
INTERNET_EXCHANGE | 1,318 | 2 | An internet exchange point (LINX LON1). |
SUBMARINE_CABLE | 697 | 1 | A subsea cable (2Africa). |
CABLE_LANDING | 1,922 | 2 | A landing point for a subsea cable. |
CDN_POP | 1,677 | 1 | A CDN point of presence (operator-prefixed id). |
DNS_ROOT_INSTANCE | 1,534 | 0 | A root-server instance. The nodes list; nothing joins to them. |
CLOUD_REGION | 91 | 1 | A cloud-provider region (aws:eu-west-1). Only 3,288 prefixes are mapped to one. |
Egress, fingerprint & transparency
| Label | Rows | Edge types | What it is |
|---|---|---|---|
VENDOR | 53 | 2 | A cloud or SaaS vendor that operates address space (cloudflare). |
TOR_RELAY | 3,191 | 1 | A Tor relay, keyed by fingerprint. |
TLS_FINGERPRINT | 765 | 1 | A JA3 or JARM TLS fingerprint. Only 261 IPs graph-wide emit one. |
CT_OBSERVATION | 29,764 | 1 | A Certificate Transparency observation, against 2.7B hostnames. github.com has none; paypal.com has none. |
DMARC_RECIPIENT | 36,119 | 1 | An 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.ROAdoes not — identify a ROA by the prefix and ASN it authorizes.FEED_SOURCE,CATEGORY,ANNOUNCED_PREFIX, andREGISTERED_PREFIXare 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.
ORGANIZATIONnames 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_BYfrom a hostname, IP or ASN), read thenameoff that row, and use that as your anchor. A zero-row result on anORGANIZATIONname 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_INSTANCEandDWI_DOMAINhold 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_OBSERVATIONis not in this group: it is reached overBGP_PATH.
Node properties
Most labels carry only name. Threat-listed indicators, announced prefixes, ASNs, and ROAs carry richer, queryable properties.
Read
coveragebeforeband. 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.explaindoes not returncoverageat all. Full contract: Coverage — what we looked at.
Threat & verdict (on threat-listed IPV4 / IPV6 / HOSTNAME)
| Property | Type | Notes |
|---|---|---|
verdictScore | Double | Reconciled triage score — prefer this over threatScore. |
verdictLevel | String | Reconciled level: NONE … CRITICAL. |
verdictBlocking | Boolean | Whether the reconciled verdict recommends blocking. |
verdictCoverage | String | What Whisper actually looked at, which is a different question from how bad it is. Read it alongside verdictLevel, never instead of it. |
verdictAdvisory | String | A 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. |
threatScore | Double | Raw feed-weighted score. Never clamped, so it keeps the full feed evidence. |
threatLevel | String | NONE / INFO / LOW / MEDIUM / HIGH / CRITICAL. |
threatSources | Integer | The 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 / threatLastSeen | epoch ms | First/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.
// 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)
| Property | Type | Notes |
|---|---|---|
isMoas | Boolean | Currently announced by more than one origin AS (MOAS). |
isAnycast | Boolean | Announced from multiple locations. |
isWithdrawn | Boolean | Currently withdrawn from the routing table. |
threatScore / threatLevel / threatSources | Double / String / Integer | Aggregate threat across the prefix. threatSources is a count of feeds here too, not a list of names. |
rir | String | The allocating regional registry. |
registrationDate / lastChangedDate | date | Allocation and last-change dates. |
ASN aggregate threat (on ASN)
| Property | Type | Notes |
|---|---|---|
maxThreatScore / avgThreatScore | Double | Max / average threat across the AS's routed prefixes. |
overallThreatLevel | String | Rolled-up level for the AS. |
hasThreateningPrefixes | Boolean | Whether any routed prefix is threat-listed. |
rir | String | The allocating regional registry. |
registrationDate / lastChangedDate | date | Allocation 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.
| Property | Type | Notes |
|---|---|---|
prefix | String | The prefix the ROA authorizes (1.1.1.0/24). Half of the ROA's identity. |
asn | Int | The authorized origin AS as a bare number (13335), not the AS13335 string form used to anchor an ASN node. |
maxLength | Int | Maximum prefix length the ROA authorizes. |
authSource | String | rpki-roa — the only value, across every ROA sampled on AS13335, AS3356 and AS8075. Filter on rpki-roa; do not filter for an irr value. |
trustAnchor | String | The RPKI trust anchor (apnic, ripe). |
validFrom / validUntil | timestamp | ROA validity window. |
Other enriched labels
| Label | Notable properties |
|---|---|
TOR_RELAY | name (fingerprint), fingerprint, exitAddressCount, source. |
CT_OBSERVATION | name (the observed cert name), certCount, firstSeen, lastSeen, wildcard. |
VENDOR | name (lowercase slug), displayName, category (cdn on cloudflare), confidence, aliases. |
TLS_FINGERPRINT | name (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_TYPE | name — one of 11 signal kinds, e.g. bulletproof-hosting, c2-hosting, toxic-neighborhood, coordinated-campaign. |
LISTED_INedges carry no queryable properties. The per-feed evidence behind a verdict (each feed's weight and first/last-seen timestamps) comes fromexplain(), which returns it as an inspectablesourcesarray.
Confirm a label before you anchor
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.