Behavioral Detections

How the Rule Engine Works

Every managed agent runs a behavioral rule engine against its live kernel event stream. Windows ETW events and Linux eBPF events are normalized to a common event shape before the rules see them, so a single rule definition fires on either OS. When a rule matches, the agent attaches the detection to its next heartbeat; the cloud persists it and pushes a live event to every open dashboard in the organization.

Each detection carries:

  • Severityinfo, low, medium, high, or critical. Rules are heuristics; severity reflects how strongly the matched pattern indicates malicious activity.
  • Title and description — what the rule looks for and what was actually observed (process names, PIDs, paths).
  • Evidence — up to 10 hand-picked events that caused the match (not a time-window dump), so you can see exactly why it fired.
  • Tags — rule-specific annotations such as file counts or window lengths.

The Rule Catalog

Rule IDWhat it detects
suspicious-exec-chainShell → downloader → shell process chains within a tight window — the classic curl http://... | bash downloader-runner pattern (PowerShell/cmd analogues on Windows).
mass-file-accessA single process reading an unusually large number of files in a short window — ransomware-enumeration / data-harvesting heuristic.
reverse-shell-heuristicA shell whose standard input/output is bound to a network socket.
privilege-escalation-noninteractive-parentPrivilege escalation launched from a non-interactive parent process (no terminal or logged-in session behind it).
unusual-outbound-from-system-daemonA system daemon or service making outbound network connections it has no business making.
mass-file-renameBulk renames to extensions like .locked or .encrypted — active file-encryption behavior.
ransom-note-patternCreation of ransom-note-style files (HOW_TO_DECRYPT* and similar).
shadow-copy-deletionBackup sabotage: vssadmin shadow-copy deletion on Windows, btrfs subvolume delete and similar on Linux.
crypto-miner-heuristicKnown miner binaries and protocols (xmrig, stratum+tcp, etc.).
backup-sabotageBackup services stopped or disabled: sc.exe, net stop, systemctl and PowerShell commands targeting VSS, WBEngine, Veeam or Acronis, plus registry writes setting Start=4 on those services.
file-encryption-sweepA single process renaming files so their extension changes to a known ransomware extension. Threshold and window are tunable (default 20 renames in 30 seconds).
suspicious-process-spawnParent-child chains characteristic of macro-delivered loaders and living-off-the-land attacks, such as winword.exe → cmd.exe or excel.exe → powershell.exe.
ransomware-kill-chainMeta-rule: fires when several of the component rules above fire on the same host within 5 minutes — a very-high-confidence "ransomware in progress" signal. How many is “several” is controlled by kill-chain sensitivity.

Thirteen built-in rules, all of them evaluated by the same engine over the same normalized capture stream on both platforms. The last three arrived in 2.6.0.0, when the separate Windows-only ransomware engine that used to own them was retired into this one. That is what brings them under the allowlist, the per-rule toggles, and the kill-chain correlation, and what makes two of the three work on Linux at all.

Rules can be toggled per organization, per tag, or per agent, and response actions (host isolation, alerting, kill-chain sensitivity) configured, under Systems → Security. Settings are pushed to each agent and take effect without a restart.

Scope order. The most specific setting wins: a per-agent override beats a tag policy, which beats the organization default. Each layer merges over the one below it per rule, so a tag policy that changes one rule inherits the rest rather than replacing them. An agent carrying several tagged policies applies them in alphabetical order of tag name.

Platform coverage

Most rules behave identically on Windows and Linux — they read the same capture stream through the same engine. Two do not, and the difference is in what the operating system makes observable, not in the rule:

RuleWindowsLinux
file-encryption-sweep Full Does not fire. This rule detects a file’s extension changing during a rename, which needs both the old and the new name. Windows ETW reports both; the Linux eBPF probes currently report only the destination, so there is nothing to compare.
backup-sabotage Full Command-line detection only. The registry half (a service disabled by writing Start=4) has no Linux equivalent; the systemd equivalents are covered by the command-line signatures.
suspicious-process-spawn Full Runs, but inert out of the box. The rule itself is cross-platform; its shipped parent list is Windows Office and mail binaries (winword.exe, excel.exe, outlook.exe, …), which never appear on a Linux host. Add your own parent→child pairs through signature additions to make it fire here.

Linux is not uncovered by this. mass-file-rename runs on both platforms and fires on any rename to a known ransomware extension, so a commodity strain is still caught on Linux. What Linux loses is the novel-extension case — a strain using an extension nobody has catalogued yet, which file-encryption-sweep catches on Windows by noticing the change itself rather than recognising the result. If ransomware coverage on Linux hosts is a specific concern, this is the gap to know about.

The agent reports this itself: a host where extension-change detection is unobservable says so in its capability report rather than leaving you to infer it from an absence of detections. A rule that cannot fire and a rule that has nothing to fire on look identical otherwise, and that ambiguity is what the report exists to remove.

Two additional rules run cloud-side rather than on the agent: fleet-baseline-deviation (a process deviates from the per-application behavioral baseline built from your own fleet) and approved-app-hash-mismatch (an approved application's primary binary hash diverges from your organization's reference hash). Both are off by default and support a shadow mode that records what would have fired without raising alerts.

Tuning the Built-in Rules

Before disabling a noisy rule, check whether it can simply be tuned.

Where each setting lives. Settings marked dashboard are set under Systems → Security, scoped per organization, per tag or per agent, and pushed to agents without a restart. The ones marked agent are read from AgentConfig.json on the host and are not settable from the dashboard.

SettingSet whereDefaultWhat it does
Kill-chain sensitivity dashboard, in the ransomware-kill-chain rule's Tune panel Medium How many component rules must fire on one host inside five minutes before ransomware-kill-chain does. Low requires every component, which is the strictest and quietest setting. Medium and High both require two today; they stay distinct so the scale keeps its meaning if a fourth component rule is added.
Raise an alert dashboard, per rule On Whether this rule's detections raise a dashboard alert. Turning it off leaves detections recorded, visible in the panel and still firing the security_detection automation trigger; it stops them interrupting you. Set per rule, so one noisy rule can be quieted without silencing the rest.
Trigger counts and windows dashboard per rule The numbers a rule fires on. Four rules expose them: see Adjusting what a rule triggers on below.
Alert cooldown agent 60 s Minimum gap between two firings of the same rule for the same process. Suppresses storms while an incident is active without hiding a second, distinct process doing the same thing.
Signature additions agent Add your own entries to the built-in signature lists — ransomware file extensions, backup service names, parent→child spawn pairs. Additive only. You can teach a rule about a strain or a product it does not know; you cannot remove a built-in signature, because silently narrowing a shipped detection is a change nobody would find later. Use the allowlist or a response exclusion to handle a false positive instead.

Adjusting What a Rule Triggers On

A rule that is noisy on one class of host is usually not wrong, it is calibrated for a different machine. mass-file-access ships expecting a laptop: 200 distinct files inside 5 seconds, spanning 3 separate user folders. A file server, a backup host or a build agent does that legitimately before lunch. Rather than switching a ransomware heuristic off because it does not suit one group of machines, the numbers can be moved.

From agent 2.7.2.0 the detection also names the folders it crossed, in its description and in its tags, so you can see which trees were involved without reading the evidence list. Those names are what the allowlist offers as checkboxes. Folders are counted by name, so the same folder under three user profiles counts as one, which is what keeps a backup agent sweeping every profile from reading as ransomware.

Open Systems → Security, find the rule, and use Tune. Values are scoped exactly like the on/off toggles: organization default, tag, or a single agent, with the narrower scope winning. A file-servers tag can raise the threshold for that class of host and leave every other machine alone.

RuleWhat you can adjustShips as
mass-file-access Files touched, window, and how many separate user folders the activity has to span 200 files / 5 s / 3 folders
file-encryption-sweep Renames and window 20 renames / 30 s
mass-file-rename Renames and window 25 renames / 60 s
ransomware-kill-chain How close together component detections must land to count as one incident 300 s

What the editor shows you

Each field shows what this scope sets. An empty field is inheriting, and the greyed number in it is the value actually in force, so you can always tell “set to 5,000 here” from “inheriting 5,000 from the organization default”. Clear empties a field and returns it to inheriting, which is different from typing the inherited number in: a pinned value stops tracking later changes to the default, and an inherited one keeps following it.

Every value has a range

Each setting has a published minimum and maximum, shown when you hover the field. Enter something outside it and the saved value is adjusted to the nearest end of the range, with the change named on screen rather than applied quietly. The ranges are enforced again on the agent, so a value that reaches an endpoint by any route is still bounded.

The minimums are not zero. A threshold of 1 does not make a rule sensitive, it makes it fire on ordinary activity, and the result looks like a broken detector rather than a configuration choice. If a rule is not useful on a host, switch it off for that scope instead.

Lowering is riskier than raising. On mass-file-access in particular, dropping home folders spanned to 1 removes the test that keeps a backup job reading a single directory tree from tripping the rule. Raising a threshold on hosts that legitimately touch many files is the safer direction, and it is the one this exists for.

Custom Detection Rules

You can author your own detections under Systems → Security → Custom detection rules. A custom rule is a condition tree over event fields rather than a script, and it is evaluated by the same engine, on the same stream, alongside the built-in rules. Custom detections appear in the detections panel, feed the security_detection automation trigger, and are subject to the same allowlist and response actions as everything else.

Why it is not a scripting language. A small scripting language is the obvious design, and it would put an interpreter for operator-supplied code on every managed endpoint. The interesting question then stops being “what can you express” and becomes “what can a careless rule cost”: CPU on a production host, memory, a catastrophically backtracking regular expression, an infinite loop inside the capture callback. A bounded condition tree sidesteps that question rather than answering it, because its evaluation cost is arithmetically capped.

So there are no loops, no variables, no arithmetic, and no regular expressions. Every operator is an ordinal string comparison. The published bounds are:

BoundLimit
Rules per organization50
Nodes in one condition tree40
Tree depth6
Operands in an in list64
Length of any single operand256 characters
Threshold count / window2–10,000 matches over 1–3,600 seconds

Shape of a rule

Rule IDs must begin with custom-. That prefix is enforced. It is what stops an authored rule from colliding with a built-in one, or impersonating one: a rule calling itself shadow-copy-deletion would inherit that rule's meaning in the kill-chain correlation, the allowlist, and every saved query.

  • Fieldstype, operation, processName, processId, path, details, providerName, plus metadata.<key> for any annotation the capture layer attached (for example metadata.parent_image). The list is closed rather than derived from the event type, so it cannot silently widen when a new field is added internally.
  • Operatorseq, neq, contains, startsWith, endsWith, in, exists.
  • Combinatorsall (every child matches), any (at least one), not.
  • Threshold — optional “N matches within W seconds”. Grouped by processId by default (“one process did this N times”, which is nearly always the intent) or by agent (“this happened N times anywhere on the host”, for a rule about the machine rather than a program). Without a threshold, the rule fires on every matching event.
  • Severityinfo, low, medium, high, critical. Note that a custom rule at high or critical can trip auto-isolation exactly like a built-in one, if you have armed it.

An empty condition never fires. A rule saved with no condition matches nothing at all. The alternative reading would make an empty rule match every event, and quietly isolate the fleet.

Rules are validated when you save them, so you see errors while you are looking at the rule, and validated again on the agent when the policy arrives. The agent does not trust the wire, because a compromised or buggy server is precisely the case where an unbounded rule would matter most. Validation reports every problem at once rather than one per round trip.

Custom rules are authored at the organization level only. Toggling one off for a tag or a single agent works normally, through the same per-rule switches as any built-in rule. Only the definition lives in one place. Per-scope definitions multiply badly: if a tag policy defines custom-foo and an agent override also defines custom-foo, every possible answer (replace? merge the trees?) surprises somebody.

Where Detections Appear

  • Live toasts — each new detection raises a severity-colored toast in the top-right of the dashboard (auto-dismisses after 8 seconds). Click a toast to open the detections panel for that agent.
  • Detections panel — a right-side drawer listing the agent's detections from the last 72 hours (including acknowledged ones), each with its severity chip, evidence, and actions.
  • Automations — every detection fires the security_detection automation trigger, which is the supported way to route detections onward to a ticket, a webhook, or a chat channel. Configure it under Systems → Automations. Note that detections do not flow into the alert-rule engine used for metric thresholds; the automation trigger is the mechanism.
  • Shadow-mode rows — a rule that is switched off still records its findings at info severity in the same list, tagged mode=shadow. This is deliberate, so you can see what a rule would have reported before enabling it — but it does mean the panel contains rows for rules you have disabled.

Acknowledging

Use Acknowledge on a row once it has been reviewed, or Acknowledge all in the panel footer to clear the backlog for one agent. Acknowledging records that a human looked at the detection — it does not suppress future firings.

Response Actions: What Happens Automatically

A detection is a finding. What the agent does about it is configured per rule: open a rule’s Tune panel under Systems → Security → Detection rules and set its response actions there. Every action is scoped the same way the rule toggles and the tuning knobs are: per organization, per tag, or per agent, with narrower scopes inheriting anything they do not set.

Each action has three states. Inherit takes the value from the scope above, and says in brackets what that currently resolves to, so an unset control still tells you what will happen. On and Off pin the decision at this scope.

ActionDefaultNotes
Open a security ticket On, for any detection above low Debounced per rule rather than per process: one ransomware sweep trips one rule across many processes, and that is one incident worth one ticket. See below for what the ticket contains.
Open a ticket Off per rule; the blanket setting above still applies Ticket when this rule fires, whatever the blanket setting says. Setting it to Off on one rule suppresses its tickets while the rest keep theirs, which is the case that previously forced an all-or-nothing choice.
Isolate host Off (opt-in) Cut the host's outbound traffic down to an explicit allow list when this rule fires. Two agent-side guards still apply and neither is settable from the dashboard: a minimum-confidence floor, and a simulate-only switch. Arming a rule here does not bypass either, so enabling it alone still yields a dry run — see Automatic Network Isolation.
Raise an alert On Show a toast and push to open dashboards. Off silences the interruption only: the detection is still recorded, still listed, and still fires the security_detection automation trigger.

Ticketing and alerting are governed separately from the isolation threshold, deliberately. The bar for telling a human is lower than the bar for taking a machine off the network, so an organization that raises its isolation threshold does not silently stop getting tickets as a side effect.

What an automatic security ticket contains

The ticket carries the rule, the triggering process and PID, the severity, the detection title and description, and the host isolation state. That last line is the point of the ordering: isolation is attempted first and the ticket is submitted with the result, so a responder opening the ticket learns immediately whether the machine is still on the network.

It says so in every case. “Host was isolated automatically.” “Not isolated — matched a response exclusion (your note here).” “NOT isolated — armed but running in dry run; this host WOULD have been isolated.” “Isolation FAILED — the host is still fully connected.” A failed isolation is more worth someone's attention than a successful one, so it is never omitted.

Response exclusions

A response exclusion exempts a process, path, or rule from acting, without hiding anything. The detection still fires, still reaches the cloud, still appears in the panel, and still opens a ticket; only the isolation is skipped, and the ticket records that it was skipped and why.

This is the control that stops a customer's backup product from isolating a production server when it stops its own VSS writer during maintenance. Use it where the allowlist would be wrong: the allowlist says “this is not worth recording”, an exclusion says “this is worth recording, but it must not take the machine off the network.”

  • Match on process name, path (glob), rule ID, or any combination. All stated clauses must hold.
  • An entry that would match everything is rejected rather than honored. An exclusion that silently disarms the whole fleet is not a configuration anyone means to write.
  • Set in AgentConfig.json and enforced on the agent rather than in the cloud. Isolation happens locally, seconds before any heartbeat leaves; an exclusion that lived in the cloud could only hide the record of an isolation that had already happened.

Triaging False Positives: the Allowlist

Legitimate tools trip behavioral heuristics — backup software renames thousands of files, performance toolkits read entire directory trees. The Behavioral Detection Allowlist exempts a specific (process, rule) pair, optionally narrowed to a file-path pattern, so a known-good app stops generating noise without disabling the rule fleet-wide.

The path scope only ever narrows. An entry never applies to another process or another rule, so msedge exempted from mass-file-access under one folder is still watched by every other rule, and mass-file-access still watches every other process. One pair can hold several entries with different path scopes, and a detection is suppressed when any one of them matches.

The fast path: "Allow this process"

  1. Open the detection in the detections panel. Rows with a known process and rule show an Allow this process button next to Acknowledge.
  2. The dialog pre-fills the process and rule. Optionally scope the exemption. Where the detection recorded the user folders it crossed, each one appears as a checkbox; tick the folders the process is allowed to sweep. You can also type a path pattern glob (e.g. *Windows Performance Toolkit*), and suggested patterns from the detection's evidence appear as one-click chips.
  3. Add a note explaining why the exemption is safe, then click Add to Allowlist.

Each ticked folder becomes its own entry, scoped to that tree. Ticking nothing and typing nothing creates the broad exemption for that process and rule, which is still a valid choice and is stated in the confirmation before anything is submitted.

If your role or your organization's policy requires a second person, the entry is queued for an administrator instead of applied. The dialog says awaiting approval rather than reporting success, and the detection is not acknowledged, because nothing has been suppressed yet.

From a detection ticket

A detection that raises a ticket carries the same action. Open the ticket and the review panel offers the folders and the path field exactly as the detections panel does, so you do not need to find the original detection to act on it. Technicians can submit from here; only an administrator can have an entry applied, and a technician's submission is always queued for approval.

Managing entries

The full list lives on the Integrations → Security tab. Each entry shows process, rule, scope (path pattern or any path), notes, and date added. Only organization admins can add or remove entries directly here. Adding an entry with the same process, rule and path scope as an existing one is rejected, but the same process and rule with a different path scope is a separate entry and is allowed, which is how one application ends up with one exemption per folder it legitimately sweeps. Allowlisted detections are dropped server-side before they are stored or trigger alerts.

Scope as narrowly as you can. Prefer process + rule + path pattern over process + rule alone, and never allowlist a broad interpreter (e.g. bash or powershell.exe) against an execution rule — that is exactly the cover an attacker wants.

A scope is matched against the detection's evidence, and one matching path is enough. A later detection that touched an excepted folder and other folders is still suppressed, because one of its evidence paths matched. Exempting one of three folders does not leave the other two reporting. Where that matters, keep the exemption narrow enough that a sweep outside it produces different evidence, or use a response exclusion instead so the detection still records while the isolation is skipped.

Approved Applications (Related, but Different)

The Approved Applications list (Systems → Approved Applications) is a software-inventory whitelist used by Smart Reports to surface unapproved installs across the fleet. It does not suppress behavioral detections — use the Behavioral Detection Allowlist for that. Keeping the two separate is deliberate: an app can be approved for installation and still warrant a look when it starts mass-renaming files.

See Integrations & Tickets for the Approved Applications workflow, and Security for the wider security model including host isolation and operator elevation.