Skip to main content
Platform
Platform Overview How It Works
Solutions
AppSec Teams Platform Engineering Pricing Blog
Sign In Request Early Access
False positive fatigue and its cost in application security teams
Back to blog

The quiet cost of false-positive fatigue in security teams

By Selin Kaya

False-positive fatigue is not primarily a tooling problem. It is a feedback loop problem. A developer who opens their hundredth scanner alert to find another theoretical vulnerability in a library function their application never calls has been taught, systematically, that scanner alerts do not correlate with real work they need to do. That developer is not being careless when they start closing alerts without investigation. They are applying a prior that the alert system itself has trained them to hold: most of these are noise.

The actual cost of this dynamic is not the ignored false positives. Those are benign by definition. The cost is the true positives that get ignored alongside them, because the developer has no reliable way to distinguish which category a given alert falls into. A scanner that produces alerts that are irrelevant the vast majority of the time is not just low-signal; it is close to useless for triage purposes, because the real findings are distributed invisibly through the noise.

Where the noise comes from structurally

SCA tools and SAST tools generate their findings from analysis of the artifact or codebase in isolation. They do not know how the artifact is deployed. They do not know which code paths execute during normal operation. They do not know which entry points accept external input versus which are internal-only. They flag every instance of a pattern or every component with a matching CVE, because the correct conservative position, given only the artifact, is that every flagged item could be reached from attacker-controlled input.

This is correct behavior from the tool's perspective. The issue is that "could be reached, given some deployment configuration" is a much weaker statement than "is reachable in this specific deployed application." The former is what the scanner can determine. The latter is what the developer needs to know to make a remediation decision. The scanner is not lying; it is answering a different, less useful question than the one the developer needs answered.

The result is that the scanner's finding rate is calibrated for the worst-case deployment, not for the actual deployment. In an application where a large fraction of the dependency tree is never invoked in any production code path, a significant portion of the findings will correspond to that unreachable code. There is no reliable way for a developer to know, without additional analysis, which bucket a given finding falls into.

The rationality of dismissal

Consider the incentive structure from the developer's perspective. They have a sprint backlog with feature work and bug fixes. The security scanner has added 40 new findings to a backlog of 200. They pick up the first finding: a critical CVE in a transitive dependency. They trace the dependency chain, find that the vulnerable function is in a library three hops deep, search the codebase for any calls to the vulnerable API, find none in their service's code, and close the ticket as not applicable. This takes 25 minutes.

They open the second finding: same pattern, different library. Another 20 minutes. Finding three: similar. By finding five, they have spent two hours on findings that were all not applicable. They have sprint commitments. At some point, the rational response is to apply the prior established by the first four findings and start moving faster through the queue, doing less thorough investigation per item.

The security team sees this as a process failure. The developer is being cavalier about security findings. But the developer's prior is not irrational; it has been built by direct experience with the actual hit rate of the scanner against their specific codebase and deployment. If the hit rate is low, the prior update from each new alert is correspondingly small. The problem is not attitude; it is information quality.

Why tuning suppression rules is the wrong fix

The typical response from AppSec teams to false-positive fatigue is to improve the scanner's suppression configuration: add more false-positive rules, tune the scanner to the specific technology stack, annotate known-non-applicable findings so the tool stops reporting them. This reduces the reported volume, which can help temporarily, but it does not address the structural cause.

Suppression rules are manually maintained. They do not update when the application's code paths change. A suppression rule added because the vulnerable function was never called in version 1.4 of the application may become wrong in version 2.0 when someone adds a new endpoint that exercises a previously-dormant code path. The suppression rule is now hiding a real finding. The tooling that was reducing noise has created a false-negative risk.

More fundamentally, suppression rules are heuristics applied to static artifact properties. They answer questions like "is this function annotated as internal-only?" or "does this finding occur in a test file?" They do not answer "is this function on a path from any external entry point in the deployed topology?" That question requires the application graph, not the scanner artifact.

What reachability context changes about the developer experience

When a finding comes with a reachability verdict, the developer's decision tree simplifies substantially. Unreachable: the vulnerability is present in the codebase, it is not on any path from an external entry point, it can be addressed on the library's normal update cycle. Reachable: this is a path that connects to attacker-accessible input; investigate and prioritize remediation.

The key property of this experience is that the developer trusts the verdict. If reachability analysis has been consistently accurate, the developer can accept an unreachable verdict without doing the manual trace themselves. That is the 25-minute investigation per finding that they were spending, multiplied across every finding in the queue.

We want to be direct about the limits here: reachability analysis is a filter, not a guarantee. A finding labeled unreachable means no path from any external entry point we tracked reaches the vulnerable code. It does not mean the code is absolutely safe; it means we found no path with current analysis. If the application's attack surface changes, the reachability model needs to be recomputed. The verdict is as current as the last analysis run. Teams should treat reachability verdicts as time-stamped conclusions, not permanent labels.

The compound effect on team dynamics

False-positive fatigue has a compounding effect that goes beyond individual ticket velocity. When developers consistently find that security findings are not actionable, security begins to be perceived as an obstacle rather than a function that provides useful signal. Security ticket compliance decreases. AppSec engineers spend increasing time on escalation and follow-up rather than on higher-value analysis work. The friction between security and engineering increases in a way that is difficult to attribute to any single cause, because it looks like a culture problem rather than an information quality problem.

The inverse is also true. AppSec teams that consistently produce finding streams with high signal quality, where the majority of findings that reach a developer require actual action, build a different kind of relationship with engineering. Developers who trust that a critical alert means something critical is reachable in their specific code are more likely to treat those alerts with proportionate urgency. The cultural shift follows from the information quality of the system, not from training programs or enforcement.

A finding stream filtered to reachable paths in the specific deployed topology is not just a smaller finding list. It is a higher-fidelity signal that, over time, recalibrates developers' prior about whether security tooling output is worth their attention. That recalibration has operational value that extends well beyond any individual sprint cycle.

See reachability analysis on your own code

Connect your repositories and apply a reachability filter to your existing scanner findings. No configuration changes to your current toolchain required.

Request early access