A hunt that misses the adversary is worse than no hunt — it creates false confidence. Knowing the failure modes is as important as knowing the hunting techniques. Every missed hunt has a root cause; most root causes are in the hypothesis or the data source, not in the analysis.
The Taxonomy of Hunt Failure Modes
Hunt Failure
├── Hypothesis failure
│ ├── Too broad (candidate flood)
│ ├── Too narrow (excludes valid attacker variations)
│ ├── Unfalsifiable (no success/failure criteria)
│ ├── Premature closure (stopped before exhausting evidence)
│ └── Wrong TTP mapping (hunting for what the attacker didn't do)
│
├── Data source failure
│ ├── Log source not available
│ ├── Log source sampled / low fidelity
│ ├── Insufficient retention (time window exceeds data age)
│ └── Field not populated (e.g., command line logging disabled)
│
└── Analysis failure
├── Threshold overconfidence (treating 0.31 as definitively benign)
├── Scope creep (hypothesis drift)
├── Confirmation bias (looking for evidence to support, not refute)
└── False negative acceptance (null result without coverage statement)
Failure Mode 1: Too Broad
Hypothesis (too broad):
"Are there any PowerShell commands in our environment that could be malicious?"
Results: 847,000 events in 30 days
Analyst can triage: ~200 events/day
Time to clear: ~4,200 analyst-days
Problem: This is not a hypothesis — it's a data dump with an implied question.
Fix — Progressive narrowing:
Round 1 (scope reduction):
"PowerShell spawned by Office applications (Word, Excel, Outlook) in past 30 days"
→ Results: 3 events
→ Triageable in < 1 hour
Round 2 (if Round 1 is clean, widen hypothesis):
"PowerShell spawned by any user application not in approved parent list"
→ Results: 47 events
→ Triageable in 4 hours
Round 3 (statistical filter):
"PowerShell commands > 500 characters OR containing -enc flag"
→ Apply across all parent processes
→ Results: 23 events
→ Triageable in 2 hours
Narrowest specific hypothesis first. Widen only if clean.
Failure Mode 2: Too Narrow / Wrong Variation
Hypothesis:
"Alert on PowerShell with -encodedcommand flag (exact string match)"
Attacker command: powershell -enc [base64]
Hunt misses: powershell /encodedcommand [base64]
powershell -e [base64]
powershell -EnC [base64] (case insensitive)
powershell.exe -ENCODEDCOMMAND [base64]
PowerShell accepts abbreviated flag forms (-e, -en, -enc, -encod…) and the parameter names are case-insensitive. An exact string match hypothesis misses 80% of real usage.
Fix: Use regex matching for known abbreviations:
| where CommandLine matches regex @"(?i)-e(n(c(o(d(e(d(c(o(m(m(a(n(d)?)?)?)?)?)?)?)?)?)?)?)? "
// Or simpler: check for the base64 pattern (long alphanum string)
| where CommandLine matches regex @"-[eE]\S* [A-Za-z0-9+/=]{50,}"
Failure Mode 3: Wrong Data Source
Example scenario: Hunt for certutil download execution.
Hypothesis: "certutil.exe with -urlcache flag appears in Windows Security Event Log"
Hunt result: 0 events
Actual state: certutil.exe ran 14 times in 30 days
Problem: Windows Security Event Log 4688 (process creation) requires audit
policy "Process Creation" with command line logging enabled.
This environment has process creation auditing enabled but command
line capture disabled → Event 4688 shows certutil.exe ran but shows
CommandLine: "(null)" — the -urlcache flag is invisible.
Data source validation before hunting:
Before hypothesis:
1. Check: Is Event 4688 present with non-null CommandLine?
→ query: SecurityEvent | where EventID == 4688 | where isnotempty(CommandLine) | take 1
→ If 0 results: command line logging not enabled → switch to Sysmon Event 1
2. Check: Is Sysmon Event 1 collected in SIEM?
→ query: Sysmon | where EventID == 1 | take 1
→ If results: Sysmon is the correct source for this hunt
Failure Mode 4: Premature Closure
Pattern:
Hunt: "Find beacons to external IPs with CV < 0.30"
Step 1: Rate filter → 2,847 results
Step 2: Peer cohort filter → 43 results
Step 3: CV calculation on top 5 (by conn_count) → all clean
Analyst conclusion: "No beacons found."
MISTAKE: Top 5 by conn_count were safe harbored after calculation.
Candidates 6–43 were never evaluated because analyst ran out of time.
Prevention — Define explicit closure criteria in the hypothesis:
Hunt is COMPLETE when:
- All 43 candidates have been evaluated OR
- All remaining candidates have conn_count < 100 AND are in safe harbor
Hunt is INCONCLUSIVE if:
- Time limit reached with candidates 6–43 unevaluated
- Document as partial hunt: "candidates 1–5 evaluated, 6–43 pending"
Premature closure without documentation is the same as not hunting at all — it produces false confidence without the work to back it.