Why most alerts are false: the base-rate problem in alert triage

Stefan Axelsson made the argument in 2000: because attacks are rare, an intrusion detector needs an almost absurdly low false-alarm rate before its alerts are mostly real [1]. Twenty-six years later it is still the best explanation of alert fatigue — and it sets hard limits on what an AI triage layer can do.

#Precision is a property of the environment, not just the detector

Let be the prevalence of malicious events among those a detector evaluates, its true-positive rate and its false-positive rate. Bayes' theorem gives the probability that an alert is real — its precision or positive predictive value:

When is small, the denominator is dominated by , so . Precision scales with the ratio of prevalence to false-positive rate. Detector quality alone cannot fix it.

Prevalence πFPR 1%FPR 0.1%FPR 0.01%
0.00011.0%9.0%49.8%
0.0019.0%49.8%90.8%
0.0150.0%90.9%99.0%
Share of alerts that are real (precision) vs how rare attacks areDetector with 99% true-positive rate. At realistic prevalence, precision is dominated by the false-positive rate. 0% 20% 40% 60% 80% 100% 1e-05 0.0001 0.001 0.01 0.1 prevalence of malicious events (log scale) precision of an alert FPR 0.01 FPR 0.001 FPR 0.0001
Precision of an alert vs prevalence for a detector with 99% true-positive rate. Each order of magnitude of rarity costs an order of magnitude of false-positive rate. SVG

A "99% accurate" detector watching events where one in ten thousand is malicious produces alerts that are real about 1% of the time. That isn't a tuning failure. It's arithmetic.

#An AI triage layer is a second detector — with the same problem

Put a triage model after detection. It sees alerts, not raw events, so its prevalence is higher, but still small. In our scenario: 1,200 alerts per day of which 0.2% relate to real incidents (about 2.4 a day). The triage model assigns each alert a score; we use a binormal model where benign scores are and malicious scores . Separability summarizes how good the model is; the ROC curve follows from the threshold :

The cost-optimal threshold

Let a missed true alert cost and an unnecessary human review cost . Expected cost per alert is

minimized where the ROC slope equals . For the binormal model the slope at is , so

We set : missing one real alert is as bad as 2,000 wasted reviews.

#Results: what separability buys

Model d′Optimal TPROptimal FPREscalated / dayPrecision of escalationsMissed true alerts / monthEscalated / day at 99.5% TPR
1.595.3%57.0%6850.3%3.41,031
2.596.4%24.4%2940.8%2.6637
3.598.4%8.8%1082.2%1.1215
Human escalations per day required to keep a given recall1,200 alerts per day with 0.2% true. Separability d' of the triage model determines how expensive the last few points of recall are. 0 250 500 750 1k 0.9 0.92 0.94 0.96 0.98 recall on true alerts (TPR) escalations per day d' = 1.5 d' = 2.5 d' = 3.5
Human escalations per day needed to keep a given recall on true alerts. 1,200 alerts/day, 0.2% true. The last points of recall are expensive, and much more so for weaker models. SVG

A weak model () at its cost-optimal threshold still escalates 685 of 1,200 alerts and misses 3.4 true alerts a month. Raising separability to escalates 108 a day and misses 1.1. Even then, escalation precision is only 2.2%: most escalations are still benign, because the base rate is still low.

And if policy demands 99.5% recall regardless of cost, the model must escalate 215 alerts a day — double the cost-optimal number — while the weak model must escalate 1,031, i.e. nearly everything.

#What this implies for AI SOC products

  • "Closes 90% of alerts" means nothing without the miss rate. Any model can close 90% of alerts; the question is how many of the ~2 real ones per day it closed along with them. Demand false-negative rates measured on seeded attacks.
  • Separability comes from evidence, not prose. A triage verdict that cites queries across identity, endpoint and network data separates classes better than one that reasons from the alert text. That is the practical meaning of grounding.
  • Raise the prevalence the model sees. Correlating alerts into incidents before triage increases and therefore precision at every threshold. Deduplicating 40 alerts from one incident into a single case is worth more than a better classifier.
  • Write the cost ratio down. is a business decision. Making it explicit is the only way to choose a threshold you can defend after an incident.

#Worked example: correlation beats a better model

Precision depends on prevalence, and prevalence depends on the unit you triage. Suppose the 1,200 daily alerts are first grouped into cases: benign alerts collapse roughly 5:1 into 240 benign cases, and the day's 2.4 true alerts belong to a single incident case. Case-level prevalence is , about twice the alert-level 0.2%.

Holding the model and its operating point fixed (TPR 96.4%, FPR 24.4%), precision of escalations rises from 0.79% to 1.62%, and humans review about 59 cases a day instead of 294 alerts. Doubling precision this way required no model improvement at all; reaching the same precision by improving the model alone would require a substantially higher .

Choosing the threshold in code

from math import log
from scipy.stats import norm

def optimal_threshold(d_prime, prevalence, c_fn, c_fp):
    t = d_prime / 2 + log((1 - prevalence) / prevalence * c_fp / c_fn) / d_prime
    return t, 1 - norm.cdf(t - d_prime), 1 - norm.cdf(t)   # threshold, TPR, FPR

print(optimal_threshold(2.5, 0.002, 2000, 1))   # (0.695, 0.964, 0.244)

In production, estimate from labeled history (or seeded attacks), set per alert class, and recompute thresholds when prevalence shifts — for example during an active campaign.

#One threshold per alert class

The cost ratio is not the same for every alert. Applying the optimal-threshold formula with to three illustrative classes:

Alert classPrevalence πC_FN / C_FPThreshold t*TPRFPR
Ransomware staging0.1%20,0000.0599.3%48.0%
Credential misuse0.3%2,0000.5397.6%29.7%
Policy violation1.0%501.5283.6%6.4%

For ransomware staging, the rational policy is to escalate nearly half of all such alerts to a human, because a miss is catastrophic. For policy violations, the same model should close almost everything automatically and accept missing one in six. A single global threshold is wrong for both. This is also the most useful question to ask any AI triage vendor: can I set the cost ratio per alert class, and can I see the resulting operating point?

#Limitations

The binormal ROC is a standard idealization; real score distributions are skewed and multi-modal. Costs are not constant across alerts — missing ransomware staging is worse than missing a policy violation — so a production system should apply different thresholds by alert class. Prevalence varies by source and by day. Scenario numbers are illustrative; the formulas are general.

#Frequently asked questions

Why are most security alerts false positives?

Because malicious events are rare. By Bayes' theorem, alert precision is roughly the true-positive rate times prevalence divided by the false-positive rate, so even a detector with 99% recall and 1% false positives produces mostly false alerts when only one event in ten thousand is malicious.

What false negative rate is acceptable for AI alert triage?

It depends on the cost ratio between a missed incident and an unnecessary review, which should be set explicitly. With a 2,000:1 ratio, a strong triage model in our scenario missed about one true alert per month while cutting escalations by over 90%.

#Sources

  1. [1] S. Axelsson, “The Base-Rate Fallacy and the Difficulty of Intrusion Detection,” ACM Transactions on Information and System Security 3(3):186–205, 2000

Measure your triage on your alerts.

Nightwatch's shadow trial reports escalations, closures and misses against seeded attacks, so you see d′ before you trust it.

Book a briefing