Files
rengine/shared/definitions/correlation.py
T
Yogesh OjhaandClaude Opus 5 e7a5359624 feat(web-assets): say when another target carries the same value
A row states that a favicon, page title, body hash, certificate, CNAME
target or address is also held by a host under a different target, and
the popover names the peers and pivots to the query that returns them.
Read against the estate, so a row on a single-scan page still reaches
the other targets.

The refusal is the feature. Measured across four unrelated estates, all
five cross-target values were a provider's and none is drawn. A carrier
on a SHARED_EDGE_HOSTS CNAME vouches for no identity. generic_page()
refuses a title that restates the status of the rows carrying it, the
soft-404 phrases and the curated edge interstitials, and it gates the
three page-derived kinds. cert_covers() requires a certificate to name
the host presenting it, so *.okta.com on a tenant is not a link. JARM
spanned all four estates and is not a cross link.

Each value is judged once before the row loop and _crossing() refuses to
fetch carriers for a value one target holds: a wildcard CNAME with 8,679
carriers cost 4.6s a page, now ~80ms.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LxAonr95Uj7Bdu4CTMCwx9
2026-09-12 23:35:34 +05:30

102 lines
3.4 KiB
Python

"""Identity kinds two hosts can share, and the thresholds that make a shared identity significant."""
from __future__ import annotations
from enum import StrEnum
MAX_GRAPH_HOSTS = 3000
MAX_HUBS_PER_KIND = 80
MIN_SHARED = 2
# a body this small is not an identity
MIN_BODY_BYTES = 512
# hidden by default at or above this share
COMMON_SHARE = 0.5
MIN_ESTATE_FOR_COMMON = 25
class CorrelationKind(StrEnum):
IP = "ip"
CNAME = "cname"
TITLE = "title"
FAVICON = "favicon"
BODY = "content_hash"
JARM = "jarm"
CERT = "cert.fingerprint"
CERT_ISSUER = "cert.issuer"
HEADERS = "header_hash"
TECH = "tech"
SERVER = "server"
CDN = "cdn"
CORRELATION_KIND_LABELS: dict[str, str] = {
CorrelationKind.IP.value: "Address",
CorrelationKind.CNAME.value: "CNAME target",
CorrelationKind.TITLE.value: "Page title",
CorrelationKind.FAVICON.value: "Favicon",
CorrelationKind.BODY.value: "Body hash",
CorrelationKind.JARM.value: "TLS fingerprint",
CorrelationKind.CERT.value: "Certificate",
CorrelationKind.CERT_ISSUER.value: "Certificate issuer",
CorrelationKind.HEADERS.value: "Header set",
CorrelationKind.TECH.value: "Technology",
CorrelationKind.SERVER.value: "Server header",
CorrelationKind.CDN.value: "CDN",
}
CORRELATION_KIND_HELP: dict[str, str] = {
CorrelationKind.IP.value: "Hosts resolving to the same IP address",
CorrelationKind.CNAME.value: "Hosts aliased to the same CNAME target",
CorrelationKind.TITLE.value: "Hosts responding with the same page title",
CorrelationKind.FAVICON.value: "Hosts serving the same favicon hash",
CorrelationKind.BODY.value: "Hosts returning an identical response body",
CorrelationKind.JARM.value: "Hosts with the same JARM TLS fingerprint",
CorrelationKind.CERT.value: "Hosts presenting the same certificate",
CorrelationKind.CERT_ISSUER.value: "Hosts presenting certificates from the same issuer",
CorrelationKind.HEADERS.value: "Hosts returning an identical set of response headers",
CorrelationKind.TECH.value: "Hosts fingerprinted with the same technology",
CorrelationKind.SERVER.value: "Hosts returning the same Server header",
CorrelationKind.CDN.value: "Hosts fronted by the same CDN or WAF",
}
# drawn by default
CORRELATION_DEFAULT_KINDS: frozenset[str] = frozenset(
{
CorrelationKind.IP.value,
CorrelationKind.CNAME.value,
CorrelationKind.TITLE.value,
CorrelationKind.FAVICON.value,
CorrelationKind.BODY.value,
CorrelationKind.JARM.value,
CorrelationKind.CERT.value,
}
)
CORRELATION_KIND_ORDER: tuple[str, ...] = tuple(k.value for k in CorrelationKind)
# a value shared with a host under another target, strongest first
CROSS_LINK_ORDER: tuple[str, ...] = (
CorrelationKind.CERT.value,
CorrelationKind.BODY.value,
CorrelationKind.FAVICON.value,
CorrelationKind.CNAME.value,
CorrelationKind.IP.value,
CorrelationKind.TITLE.value,
)
CROSS_LINK_KINDS: frozenset[str] = frozenset(CROSS_LINK_ORDER)
# identities read off the page
CROSS_PAGE_KINDS: frozenset[str] = frozenset(
{
CorrelationKind.TITLE.value,
CorrelationKind.FAVICON.value,
CorrelationKind.BODY.value,
}
)
MAX_CROSS_LINKS = 3
MAX_CROSS_PEERS = 6
MAX_CROSS_VALUES = 500
# the share of a project's targets past which a value is the estate's norm
CROSS_COMMON_TARGET_SHARE = 0.5
MIN_TARGETS_FOR_COMMON = 4