Trinetra

DetectionLearning

ConnectingAwaiting observations.—Read only
  1. Workspace
  2. Learning
One-way boundary not verified.

Continuous learning

Connecting

What each detector measures, the fields it measures it on, and the thresholds it compares them against. Read here before trusting a score anywhere else in the console.

  1. Feature ingestSliding windows and baselines, computed once and shared by every detector.
  2. Drift analysisDistribution shift in the feature stream, recorded as a signal.
  3. Operator feedbackAnalyst verdicts recorded against alerts.
  4. Dataset synthesisLabelled examples assembled offline from stored evidence.
  5. Offline retrainA candidate model is trained outside the pipeline.
  6. Safety evaluationPrecision, recall, false-positive rate and latency gates.
  7. Shadow verificationThe candidate scores live traffic without alerting.
  8. Champion deployA human promotes the candidate. Nothing promotes itself.

Steps 1 to 3 are observed continuously. Steps 4 to 8 require an operator decision: a candidate model is trained offline, evaluated, shadowed, and promoted by a person. Nothing in this pipeline retrains or promotes itself.

Detector reference

Field names are the ones the feature engine emits. Gates are the thresholds each detector compares against. Live state comes from the detector registry; a detector with no reading is named, not assumed healthy.

c2_beacon

C2 beaconingStatisticalUnavailable

Finds a command-and-control callback: one source talking to one destination on a regular interval, with a stable payload, to somewhere it has never been before.

Requires: Regular timing on its own reports nothing, because NTP, software updaters and monitoring agents are all near-perfect beacons. At least two independent corroborating signals must hold before this detector emits anything.

c2_beacon.periodicity_score>= 0.7Regularity of the inter-arrival series, scaled by how many intervals were actually observed, so three lucky connections cannot score high.
c2_beacon.interarrival_cv<= 0.25Coefficient of variation of the gaps between check-ins. A beacon is tight; a human is not.
c2_beacon.interarrival_meanThe average gap. Check-ins outside a plausible range are not treated as beacons at all.
c2_beacon.interarrival_stdev<= 30 sAbsolute jitter. Regular in relative terms but hours of absolute jitter is not a beacon.
c2_beacon.autocorrelation_periodicityAlternative path for a beacon whose intervals follow a repeating pattern and therefore scores poorly on plain variability.
c2_beacon.spectral_peak_ratio>= 0.45 over >= 12 intervalsThe same alternative, measured as energy concentration in the spectrum. Needs a long enough series to mean anything.
c2_beacon.byte_stability_cv<= 0.3Payload size stability across check-ins: fixed-size check-ins are the signature.
c2_beacon.destination_rarity>= 0.5 to corroborateHow unusual this destination is for this source.
c2_beacon.destination_port_rarity>= 0.5 to corroborateHow unusual this destination port is for this source.
c2_beacon.is_internal_destinationA beacon leaves the estate. An internal destination is not a callback.
c2_beacon.corroborating_signalsCount of the independent signals that held. Below two, nothing is reported.

c2_ml

C2 beaconingSupervisedUnavailable

A classifier over the same pair-window features, for beacons whose timing is regular but not textbook. It runs alongside c2_beacon rather than replacing it.

Requires: A champion model is registered and its feature contract matches. Probability must clear the model's own decision threshold, which is recorded with the model, not hard-coded here.

c2_ml.c2_probability>= the model's decision_thresholdCalibrated probability that this pair is a beacon.
c2_ml.interarrival_countHow many check-ins the classifier was given. Too few and it abstains.

dga

Domain generationSupervisedUnavailable

Recognises algorithmically generated domains: malware walking a list it generates, so the names look random but are not random to the model.

Requires: A champion DGA model must be registered. Below the calibrated probability threshold the query is treated as ordinary name resolution.

dga.dga_probability>= 0.85 unless the champion records its own thresholdModel probability that the queried domain is generated.
dga.dns_char_entropyShannon entropy of the domain. Generated names sit high; dictionary names sit low.
dga.dns_payload_length>= 8Length of the queried name. Very short names are not worth a verdict.
dga.dns_label_countNumber of labels in the queried name.
dga.dns_nxdomain_ratio_60sShare of this host's lookups that returned NXDOMAIN. A walking list mostly misses.

dns_tunnel

DNS tunnellingHybridUnavailable

Finds data being carried out inside DNS queries: long, unique, high-entropy subdomains under one zone, which is what an exfiltration channel over port 53 looks like from the outside.

Requires: Lexical and behavioural evidence together. A single long name is not a tunnel; a tunnel is a pattern across many of them.

dns_tunnel.dns_domain_length>= 60Length of the full queried name. Tunnels pad the subdomain to carry payload.
dns_tunnel.dns_char_entropy>= 3.6 bits/charEntropy over the subdomain characters. Encoded payload is high entropy; a real zone name is not.
dns_tunnel.dns_unique_name_ratio_60s>= 0.8Share of this host's queries that are unique names. A tunnel almost never reuses a name.
dns_tunnel.dns_query_count_60s>= 20Query rate from this host. A tunnel sustains volume.
dns_tunnel.dns_txt_ratio_60s>= 0.3Share of queries that are TXT, the record type most used to smuggle a response back.
dns_tunnel.dns_hex_ratioShare of the subdomain that is hex digits, the cheapest encoding to use.
dns_tunnel.dns_subdomain_depthLabel depth below the registrable domain. Tunnels nest to create space.

tls_malware

TLS malwareRuleUnavailable

Identifies malware by the shape of its TLS handshake rather than its contents. The payload is encrypted, but the fingerprint of the client stack is not.

Requires: A curated fingerprint list, or a champion model over TLS metadata. Confidence is capped so a single one-sided sighting never reads as certainty.

tls_malware.ja4_list_countlistings above 3 are not rare on their ownHow many independent rows in the curated list carry this JA4. A repeat is stronger evidence than a one-off.
tls_malware.tls_malware_confidencecapped at 0.9Evidence-based confidence: 0.6 for a match, +0.2 when both handshake sides agree, +0.15 when the fingerprint repeats.
tls_malware.tls_malware_probabilityModel probability from TLS metadata, when a champion model is registered.
tls_malware.tls_sni_presentWhether a server name was offered. Malware frequently omits it.
tls_malware.fingerprint_samplesTotal sightings across both sides of the handshake, capped for the evidence count.

exfiltration

Data exfiltrationStatisticalUnavailable

Finds sustained outbound bulk transfer to a destination the host does not normally use. Judged over the widest window, because transfers take time.

Requires: Volume alone never fires. The transfer must be outbound from inside the estate, and at least one non-corroborating signal must hold: a rare destination, a baseline deviation, or a flow-size deviation.

exfiltration.bytes_out_total_300s>= 10 MBTotal bytes sent by this host over five minutes.
exfiltration.orig_resp_byte_ratio_300s>= 20How lopsided the transfer is. Only measurable when the sensor sees both directions.
exfiltration.bytes_out_per_sec_60s_zscore>= 4.0Outbound rate against this host's own history.
exfiltration.destination_rarity>= 0.9How new this destination is for this host.
exfiltration.destination_port_rarity>= 0.9How new this destination port is for this host.
exfiltration.outbound_flow_bytes_zscore>= 4.0Per-flow size against this host's flow-size baseline.
exfiltration.bytes_out_per_sec_60s_baseline_warmWhether enough history exists to compare against. A cold baseline is reported as cold, never as clean.
exfiltration.mean_duration_300s>= 60 sMean connection duration. A sustained transfer runs long.

recon

ReconnaissanceRuleUnavailable

Separates a scanner from a busy legitimate client. Fan-out alone describes a proxy, an updater or a backup agent, so a second, independent gate must also hold.

Requires: Behind a one-way tap the response side is never observed, so failures cannot be measured. The detector then falls back to an origin-only discriminator: a scan opens roughly one flow per target, and each probe is small.

recon.unique_dst_ports_60s>= 20Distinct destination ports touched, which is what a vertical scan is.
recon.unique_dst_ips_60s>= 25Distinct destination hosts touched, which is what a horizontal scan is.
recon.flow_count_60s>= 20Flows from this host in the window. Too few and there is no pattern to read.
recon.failed_ratio_60s>= 0.8Share of connections that failed, when the sensor can observe the response side.
recon.syn_ratio_60sShare that were SYN without establishment. Same caveat as above.
recon.mean_duration_60s<= 1.0 sMean connection lifetime. A probe is short; a working session is not.
recon.dst_port_entropy_60sSpread of the destination port choices, which separates a sweep from a client reusing a few services.

ddos

DDoS floodHybridUnavailable

Finds a flood toward one victim. The alert is attributed to the destination, because a flood has many sources and attributing it to one of them would scatter the incident.

Requires: Rate alone cannot tell a flood from a scan, so the traffic must be concentrated on few destination ports. A baseline comparison is reported as cold when there is no history, and a cold baseline is not evidence of an attack.

ddos.syn_rate_1s>= 500SYN flows per second toward the victim.
ddos.flows_per_sec_1s>= 1000Total flows per second toward the victim.
ddos.packets_per_sec_1s>= 20,000Packet rate toward the victim, which catches a flood made of small packets.
ddos.unique_dst_ports_1s<= 10How many ports the flood spreads across. A flood concentrates.
ddos.unique_src_ips_5s>= 50 to corroborateDistinct sources in five seconds.
ddos.src_ip_entropy_5s>= 4.0 bitsSpread of the source addresses. High entropy means distributed or spoofed.
ddos.amplification_ratio_5s>= 5.0Bytes received against bytes sent, for reflection attacks. Only measurable with both directions.
ddos.flows_per_sec_60s_zscore>= 10x the baseline meanCurrent rate against this destination's own history.

anomaly

Benign trafficStatisticalUnavailable

Finds hosts whose overall behaviour is unlike themselves. It never raises a threat on its own: it supplies corroborating context to the detectors that do.

Requires: At least ten events for this host, and a champion model whose feature contract matches.

anomaly.anomaly_score>= the model's score_thresholdHow far this host's current behaviour sits from its trained profile.
anomaly.anomaly_thresholdThe threshold recorded with the champion model that produced the score.
anomaly.flows_per_sec_60sCurrent flow rate for this host.
anomaly.bytes_out_per_sec_60sCurrent outbound rate for this host.
anomaly.unique_dst_ports_60sCurrent fan-out for this host.
anomaly.unique_dst_ips_60sCurrent distinct-destination count for this host.
anomaly.dns_queries_per_sec_60sCurrent resolver load for this host.

Sliding windows and entity baselines

One window bundle is computed per entity and carries every window size at once, so a detector can compare a one-second burst against a five-minute baseline without a join. Three entity perspectives are tracked, because the same flow is evidence of different things depending on which end you look from.

1s window

Rate bursts. syn_rate_1s, flows_per_sec_1s, unique_dst_ports_1s.

5s window

Distribution. unique_src_ips_5s, src_ip_entropy_5s, amplification_ratio_5s.

30s window

Short-horizon DNS and TLS behaviour.

60s window

Baselines. flows_per_sec_60s, bytes_out_per_sec_60s, unique_dst_ports_60s.

300s window

Transfers. bytes_out_total_300s, orig_resp_byte_ratio_300s.

Baselines are exponentially weighted per entity and per metric, and are explicitly cold until enough observations exist. A cold baseline is reported as cold; it is never read as a clean result.

flows_per_sec_60sEWMA mean and stdev per entity, compared as flows_per_sec_60s_zscore.
bytes_out_per_sec_60sThe exfiltration baseline metric. Reported warm only after enough observations.
syn_rate_5sSYN volume per entity.
unique_dst_ports_60sDestination fan-out per entity.
unique_dst_ips_60sDistinct destinations per entity.
dns_queries_per_sec_60sResolver load per entity.

Feature drift history

Drift events are signals only; they never trigger retraining or promotion.

Loading drift history

Loading drift history…

Analyst feedback

Connecting

Verdicts recorded during alert investigation. They are the only labelled signal the learning loop receives, and they are written by a person.

Loading analyst feedback

Registered training datasets

Reading the model registry…