Lesson 1 of 5 · 25 min read

Precision, Recall, and Robustness — The Detection Quality Triangle

A detection rule is a binary classifier: for every event, it decides “alert” or “no alert.” Two classic machine-learning metrics — precision and recall — measure how good that classifier is. But in adversarial settings, a third dimension matters just as much: robustness. This lesson defines all three, shows how they interact, and builds the vocabulary you’ll use throughout the rest of this module.


Precision: How Often Are Your Alerts Real?

Precision = TP / (TP + FP)

A rule with 100 alerts per day — 20 real threats, 80 noise — has 20% precision. Analysts spend 80% of their time on alerts that lead nowhere.

What drives low precision:

What drives high precision:


Recall: How Many Attacks Are You Catching?

Recall = TP / (TP + FN)

A rule that fires on net.exe user /add has 0% recall for attackers using net1.exe, dsadd, the Active Directory Users GUI, or direct LDAP writes. All four are valid ways to add a user — none trigger the rule.

What drives low recall:

What drives high recall:


Robustness: Does the Rule Survive an Attacker Who Knows It Exists?

Precision and recall describe how the rule performs against a passive dataset. Robustness describes how it performs when the attacker actively tries to evade it.

Robustness = (steps required to evade the detection)

This is Summiting the Pyramid in practice — L0–L4.

LevelWhat the rule targetsEvasion cost
L0Atomic indicator (hash, IP)Seconds
L1Specific tool variant (filename, mutex)Minutes
L2Common capabilities (specific function calls)Hours
L3Behavioral indicator (actions regardless of tool)Days to weeks
L4Implementation-agnostic (OS primitives, kernel-level)Months

The net.exe example has low recall AND low robustness (L1). An attacker running T1136.001 through any other binary path — or renaming net.exe — evades it completely.


The Triangle: You Can’t Maximize All Three Simultaneously

         Precision
            /\
           /  \
          /    \
         /      \
        /________\
    Recall      Robustness

The three dimensions pull in different directions:

There is no perfect rule. Every detection is a deliberate trade-off. The engineering discipline is knowing which corner of the triangle to sacrifice for your specific threat model and analyst capacity.


Working Example: Scoring a Net User Rule

detection:
  selection:
    Image|endswith: '\net.exe'
    CommandLine|contains: 'user /add'
  condition: selection
DimensionScoreWhy
PrecisionMediumnet.exe user /add runs legitimately in enterprise IT; domains provisioning new staff will trigger this
RecallLowMisses net1.exe, dsadd, PowerShell AD cmdlets, direct LDAP, GUI-based account creation
RobustnessL1Rename net.exe or use any alternative tool → complete evasion

Improving recall without destroying precision:

detection:
  selection_net:
    Image|endswith:
      - '\net.exe'
      - '\net1.exe'
    CommandLine|contains: 'user /add'
  
  selection_dsadd:
    Image|endswith: '\dsadd.exe'
    CommandLine|contains: 'user'
  
  condition: 1 of selection_*

This raises recall (catches net1.exe and dsadd) but still misses PowerShell and GUI paths. Robustness remains L1-L2.

Improving robustness (at precision cost):

logsource:
  product: windows
  category: user_management  # Sysmon Event 4720 or Security Event 4720

detection:
  selection:
    EventID: 4720            # A user account was created
  filter_expected:
    SubjectUserName|endswith: '$'   # machine accounts
  condition: selection and not filter_expected

This targets the outcome (account created, Event 4720) regardless of what tool was used. Recall and robustness jump to L3+. Precision drops: 4720 fires for all legitimate IT provisioning — you need additional context (time of day, who created it, domain vs local) to separate malicious from legitimate.

On Detection: Why Detections Fail— SpecterOps Summiting the Pyramid— CTID / MITRE Engenuity