Run Silent.
Run Deep.
Track Everything.

CMMC-Ready NDR for Industrial Infrastructure

ML detection on OT and IoT protocols. Built for compliance.

Built on the OCCAM detection engine — predictive behavioral detection that catches what signatures miss. Air-gap native. No cloud. No telemetry. The plant's data stays at the plant.

Five lenses on every host. One risk picture.

Each lens is a different way to catch a threat, layered across the license tiers. Anomalies, Behavioral, and Performance are ML/statistical — the engine pipeline below zooms into how they work. All five compound on the unified Detections page.

ALERTS powered by Suricata signature + protocol IDS FREE IP REPUTATION powered by AbuseIPDB known-bad IP lookups BASIC ANOMALIES powered by iForest · HBOS population outliers (iForest default) PROFESSIONAL BEHAVIORAL powered by OCCAM tokenizer → HMM Viterbi PROFESSIONAL PERFORMANCE powered by Odometry per-asset drift + SLA breach FREE

The ML engine stack. One layered prediction.

Zooming into the Anomalies, Performance, and Behavioral lenses above: iForest scores population outliers, Odometry tracks each host's drift from its own baseline, and OCCAM tokenizes behavior before its HMM predicts the attack sequence. Arrows show how output feeds the next layer; together they turn a stream of mystery scores into a single predictive alert. (Suricata Alerts and IP Reputation are the other two lenses — signature and lookup detections, not ML.)

INPUT EVE + windowed feature vectors flow / dns / tls tcp_perf / udp_perf payload_entropy 15-min asset windows iFOREST Isolation Forest (online) "Is THIS flow anomalous?" → population outliers anomaly_score 0–1 catches encrypted / novel tooling ODOMETRY Welford z-score (online) "Did THIS HOST drift from itself?" → per-host context drift events SLA breaches Welford streaming OCCAM Behavioral tokenizer "Is the drift security-meaningful?" → ATT&CK narrative tactic + surprisal token vocabulary 15-min windows · uses Odometry baseline HMM HMM Viterbi predictor "Does the SEQUENCE match an attack?" → predictive alert disposition pre-intrusion alerts consumes OCCAM tokens Suricata + plugins raw events per-host score Anomalies page per-host context Reliability page security narrative OCCAM page predictive alert Occam page
Layer 1 · iForest

Per-host anomaly scoring

An Isolation Forest — an unsupervised ML algorithm that scores each host's behavioral profile against the current population, trained online each run. Catches what signatures don't: encrypted threats, novel malware, custom tooling.

  • Builds many random decision trees; anomalies isolate quickly — short paths = high score
  • No distribution assumptions — works on encrypted payloads where deep inspection fails
  • Pre-trained baseline ships with Rockfish; supports retraining against your own corpus
  • Output: anomaly_score in [0 .. 1] per flow
  • Surfaces in the report's Anomalies page
Isolation Forest scoring
# How a flow gets scored flow ──► [tree₁ tree₂ ... tree₁₀₀] │ ▼ avg_path_length │ ▼ anomaly_score = 2^(−avg / c(n)) # Practical outputs 0.05 normal traffic 0.50 borderline / unusual 0.85 strong anomaly 0.95+ near-certain anomaly
Layer 2 · Odometry

Per-host drift & reliability

A per-asset baseline built online with Welford's streaming mean/variance. Each 15-minute window is scored by z-score — standard deviations from the host's own running mean — and windows that deviate, or breach SLA, are flagged. The same machinery catches network reliability issues and the early signal of host compromise.

  • One baseline per asset, updated incrementally — no training data needed
  • Per-feature z-scores make drift interpretable: "TCP retransmits 4.2σ above this host's norm"
  • Catches dual-use signal: degraded servers and stealthy compromise
  • Output: drift events, SLA-breach windows, per-feature z-scores
  • Surfaces in the report's Reliability page; also feeds OCCAM
Odometry per-asset baseline
# Per-feature z-score vs the host's own baseline asset_10.0.12.45 (15-min window) ├── tcp_handshake_rtt z-score 4.2σ ├── dns_failure_ratio z-score 3.1σ ├── retransmit_ratio z-score 1.4σ └── ... z_i = (x_i − μ_i) / σ_i (Welford online μ, σ) # Verdict state = drift (4.2σ > threshold) state = sla_breach (DNS fail > 0.30)
Layer 3 · OCCAM

Behavioral tokenization & ATT&CK mapping

Every 15 minutes, for every asset, OCCAM aggregates window stats and emits tokens — short labels representing observed behavior categories — each with a surprisal score in bits and an ATT&CK tactic. Translates raw drift into a security narrative an analyst can actually read.

Note: Rockfish OCCAM is a behavioral tokenizer, not the public OCCAM-rules YAML grammar at sigmahq.io. Same name, different thing.

  • Token vocabulary: encrypted-ratio-high, unusual-port-mix, slow-handshake, …
  • Each token mapped to one of MITRE ATT&CK's 14 tactics
  • Surprisal score computed from the Odometry baseline — "rare for this asset" is the standard, not "rare for the network"
  • Patent-pending behavioral signal compression
  • Surfaces in the report's OCCAM page; consumed by OCCAM
OCCAM tokenizer output
# Token emitted per asset / 15-min window { "asset": "10.0.12.45", "window": "2026-04-29T14:00Z", "token": "encrypted-ratio-high", "tactic": "exfiltration", "surprisal": 8.7, "features": [ "entropy_toserver=7.94", "pcr=0.92", "bytes_sampled=8192" ] }
Layer 4 · HMM

Sequence prediction & pre-intrusion alerts

A Hidden Markov Model over the OCCAM token sequence per asset. Named for Occam's razor: when several attack paths could explain the observed sequence, pick the simplest. The Viterbi algorithm scores how strongly the recent sequence resembles a known attack path.

  • Forecasts attacks while they're still in progress — before exfil completes
  • Disposition per token: suppressed / investigate / present / elevated
  • Suppresses isolated anomalies that don't match any known sequence — major false-positive cut
  • Explainable via Viterbi paths: "this token completed the recon → lateral → exfil path"
  • Surfaces in the report's Occam page; pre-intrusion alerts route to MQTT/Kafka
OCCAM Viterbi prediction
# Recent OCCAM tokens for asset 10.0.12.45 t-45m recon-scan-light surprisal 5.1 t-30m unusual-port-mix surprisal 6.0 t-15m encrypted-ratio-high surprisal 8.7 t- 0m outbound-volume-spike surprisal 7.8 # Viterbi match (best HMM path) recon → discovery → exfiltration ↑ likelihood: 0.91 ➜ disposition: elevatedPRE-INTRUSION ALERT

The whole stack, at a glance.

The Radial Sonar is the at-a-glance situational view: every flow plotted by protocol (spoke) and by risk (radius). The radius is the compounded output of every engine — one screen where a host on the perimeter means "look here now." It answers where; the swimlane below answers who.

How the layers map to the sonar

  • Normal — iForest score low & Odometry within baseline. Inner rings.
  • Internal — benign asset-to-asset traffic, similar inner-ring placement.
  • Suspect — iForest elevated or Odometry drift fired. Mid-ring placement; OCCAM token attached.
  • Alert (pulsing) — OCCAM disposition elevated. Outer-ring perimeter, where your eye lands first.

The dashed threshold ring is the operator's risk-cutoff knob — everything outside it deserves attention. Time-window control replays the last 1–60 minutes so you can scrub through an unfolding incident frame by frame.

See a Sonar Demo

The sonar shows you where. The swimlane shows you who.

When a host lands on the perimeter, the Detections page is where you work it. Each detection lens becomes a lane and time runs left to right — when bright cells line up vertically, multiple independent engines are firing on the same host at the same moment. That agreement is what separates a real incident from a single noisy detector.

Co-firing swimlane

  • One lane per lens: iForest (anomaly), SIGMA + OCCAM (behavioral), Suricata (alerts)
  • Cell brightness = intensity, normalized per lane — surprisal and hit-counts aren't directly comparable, so each lane keeps its own scale
  • Vertical stacks of bright cells = co-firing: independent confirmation, not one detector crying wolf
  • The worst host falls out of the noise — no single tuned threshold required
Detection swimlane
# Detections · last 12h · per-host co-firing time → iForest ░░▁▂▃▄▆███▆▃ SIGMA ░░░░▁▂▃▇██▅░ OCCAM ░░░░░▁▃███▆▂ Suricata ▃░▂░▁▂▃▇█▇▃░ ▲▲▲ co-firing → 10.0.12.45 flagged
Top Hosts by Combined Risk
# ranked once, across every lens HOST RISK LANES FIRING 10.0.12.45 0.94 iForest·SIGMA·OCCAM·Suricata 10.0.7.31 0.71 iForest·OCCAM 192.168.4.10 0.58 Suricata·SIGMA 10.0.3.92 0.41 Suricata # <2 lenses on a host → Detections page hidden

Combined-risk table — the centerpiece

  • Every host ranked by one combined-risk score that folds in every firing lens
  • The contributing lenses are listed inline — you see why a host ranks, not just that it does
  • One prioritized list instead of cross-referencing four pages
  • Suppressed when fewer than two lenses are active — with one lens it's just a worse Alerts view, so it doesn't show at all

Ready for CMMC compliance?

Deploy Rockfish NDR in minutes. Single binary. No dependencies. Full pipeline.

We built this for Defense Industrial Base contractors.

Now we want to prove it.

We are looking for defense contractors and C3PAOs to deploy Rockfish NDR in a production environment at no cost. Slots are limited.

Requirements are simple: you run it, we support it, you tell us what you think. If that sounds like a fair trade, let's talk.