Compositional Anomaly Detector (CAD) — Multi-Modal Host Anomaly Detection
Aggregate z-score on per-host traffic is structurally broken for multi-modal hosts. A FortiGate with 11 interfaces (outside / inside / DMZ × 4 / IPSec / HA-Sync / mgmt) has 11 different normal behaviors — collapsing them into one mean produces close to 100% false positives when any single mode shifts. CAD decomposes the aggregate by peer class, builds per-(host, peer-class, hour-bucket) baselines, and detects via KL-divergence plus per-suspect-class spikes. Result: 90% noise reduction on multi-modal hosts since v4.32.55.
The detector lives alongside the legacy cyber_host_baseline_shift on the /anomalies page and now drives all paging decisions for multi-interface devices: firewalls, hypervisor clusters, jump boxes, replication endpoints. Without CAD, every operator-relevant host quietly produced a noisy critical incident every hour. With CAD, only the genuinely-anomalous compositional shifts trigger.
10-class peer classifier · per-interface decomposition
Every host’s traffic is decomposed into N (host, peer-class) streams via the classifier in peer-classifier.ts: transit_isp, ixp_peer, ixp_route_server, internal_lan, dmz, ipsec_tunnel, ha_sync, mgmt, monitoring, unknown. Each (host, peer-class, hour-bucket) carries its own EWMA baseline in host_class_baseline — so the same FortiGate has 11 separate, independent baselines, one per interface, not one collapsed mean across all 11.
16 service-role profiles for security-zone-aware detection
PROFILE_OUTSIDE_WAN, PROFILE_INSIDE_LAN, PROFILE_HA_HEARTBEAT, PROFILE_DMZ_WEB, PROFILE_DMZ_DB and 11 more. Each profile encodes which peer classes are expected and which are suspect for that interface’s security zone. Outside spike on internal_lan = exfiltration; inside spike on transit_isp = compromised host; HA-sync spike on anything = fabric abuse. Same FortiGate, three completely different anomaly classifications.
Triple-gate severity (v4.32.56)
CRITICAL severity now requires all three gates: (1) semantic gate — dominant-shifted peer-class must be in suspect-list for this role’s profile; (2) volume floor — critical requires ≥1 MB observed bytes; (3) direction guard — obs/baseline < 0.2 is collapse not attack, downgrade. Together these gates eliminated 90% of pre-v4.32.56 critical incidents on multi-modal hosts.
SNMP ifAlias role inference
For each unknown interface, RoutePulse queries SNMP IF-MIB::ifAlias and runs 16 regex patterns against the operator-maintained alias strings (“Cogent Zurich”, “outside-Telecom”, “vMotion”, “HA-Sync”) to suggest a role with top-5 confidence-ranked candidates. Operator confirms or overrides in the Pending Review tab; coverage is 95%+ for SNMP-managed devices, 0% for pure clients (where manual catalog or PTR pattern takes over).
Key Capabilities
- 10-class peer classifier (
peer-classifier.ts): transit_isp, ixp_peer, ixp_route_server, internal_lan, dmz, ipsec_tunnel, ha_sync, mgmt, monitoring, unknown - 16 PROFILE_* semantic constants encoding expected vs suspect peer-class composition for each service-role / security zone
- Per-(host, peer-class, hour-bucket) EWMA baselines in
host_class_baselinePostgres table — no aggregation across interfaces - KL-divergence detection + per-suspect-class spike for mathematical rigour beyond simple z-score
- Triple-gate critical-severity decision: semantic + volume-floor + direction-guard (90% noise reduction vs pre-v4.32.56)
- SNMP
ifAliasrole inference: 16 regex patterns, top-5 confidence-ranked suggestions, one-click apply in Pending Review tab - 39 catalog roles with operator-curated trust hierarchy: manual catalog > SNMP ifAlias > PTR pattern > Shodan/nmap > traffic composition heuristic
- Role-tag sync:
hosts.ml_role(legacy pipe-string) +hosts.role_tags(text[] + GIN index) kept in sync for filter compatibility - Catalog-driven ML primitives via Role Catalog (v4.28+) — replaces the hand-coded role decisions of v4.20
- Live on production /anomalies page since v4.32.55 (2026-05-22)
Engineered and operated by the GOLINE SOC & Network Engineering team.
Explore all RoutePulse features →