Security teams are drowning, and the flood is man-made. A mid-size fintech running Veracode's SAST, DAST, and SCA suite across 40 applications can generate well over 10,000 open findings in a single quarter — most flagged "high" or "critical" by default, few ranked by whether they're actually reachable in production. Analysts triage the same buffer-overflow-in-a-dead-code-path finding every scan cycle because the tool re-surfaces it, not because anything changed. Multiply that across a portfolio, and a five-person AppSec team spends more hours re-reviewing stale alerts than shipping fixes.
This is appsec alert fatigue: the point where volume and noise overwhelm signal, and engineers start reflexively dismissing warnings — including the ones that matter. It's not a people problem. It's a tooling and prioritization problem, and it's become one of the defining failures of legacy static-and-dynamic scanning platforms like Veracode. Below, we break down why it happens, what it costs, and how Safeguard's supply-chain-aware approach cuts the noise instead of just cataloging it.
Why does appsec alert fatigue happen in the first place?
It happens because most scanners are built to maximize detection, not to score actual exploitability. Veracode's SAST engine, like most legacy static analyzers, flags a pattern the moment it matches a known-vulnerable code shape — regardless of whether that code path is reachable from an entry point, whether the vulnerable function is ever called with attacker-controlled input, or whether a WAF or runtime guard already neutralizes it. A 2024 analysis of enterprise SAST output found that fewer than 5% of "critical" findings correspond to a genuinely exploitable condition once reachability is checked. The remaining 95% still land in the same queue, tagged with the same severity, demanding the same review cycle from a human who cannot tell the difference without doing the reachability analysis manually.
Layer SCA on top and the noise compounds. A typical Java or Node service pulls in 150–400 transitive dependencies. When a new CVE drops — and NVD published over 40,000 CVEs in 2024 alone, a record high — every application that merely imports the affected package lights up, whether or not the vulnerable function is ever invoked. Teams end up patching dependencies they don't call, on a timeline dictated by CVSS base score rather than actual risk.
How many alerts are security teams actually drowning in?
Enterprise AppSec teams routinely carry backlogs in the tens of thousands, and most of it never gets resolved. Veracode's own State of Software Security research has repeatedly found that a majority of discovered flaws remain open a year after discovery, and that "security debt" — accumulated unfixed findings — is now the norm rather than the exception across the industry. Internally, we've seen customers migrating off Veracode with SCA + SAST backlogs exceeding 18,000 open items across a 60-repo portfolio, accumulated over 18–24 months of quarterly scanning.
The math explains why: if a single quarterly scan on a 200-service estate surfaces 3,000 new findings and a team can realistically triage 200 per week, the backlog grows every quarter regardless of how hard anyone works. This is the mechanical root of alert fatigue — not laziness, arithmetic. Once the backlog crosses a few thousand items, teams stop trying to clear it and start triaging only what's loudest, which is precisely when a real critical vulnerability gets lost in the pile.
Does Veracode's scoring model make prioritization harder?
Yes, because CVSS-and-severity-label scoring treats every match to a vulnerable pattern as equally urgent, regardless of context. Veracode surfaces severity largely from CVSS base scores and static pattern matches, which describe theoretical worst-case impact, not the likelihood that a given deployment is actually exposed. A CVSS 9.8 in a logging library that's imported but never invoked in a request path is not equivalent in risk to a CVSS 7.5 in an authentication handler that processes every login. Under a severity-label-only model, both get the same red badge, the same SLA clock, and often the same escalation email to the same overloaded engineer.
This is compounded by duplicate and re-flagged findings. Because many legacy scanners don't track finding identity cleanly across code changes and re-scans, the same underlying issue can reappear as a "new" finding after a refactor, a dependency bump, or even a scan-engine version update — forcing teams to re-triage work they'd already closed out. Security teams we've spoken with during migrations describe re-litigating the same handful of low-risk findings for multiple scan cycles running, each time with the same "not exploitable, deprioritized" conclusion, because the tool has no memory of the prior decision surviving the next code change.
What does alert fatigue actually cost an organization?
It costs real vulnerabilities getting fixed late — or not at all — because they're buried under noise. Verizon's Data Breach Investigations Report has for years identified exploitation of known, unpatched vulnerabilities as a top initial-access vector in confirmed breaches, and post-incident reviews frequently find the exploited CVE had already been flagged by the org's own scanner, sometimes months earlier. The finding wasn't unknown. It was unactioned, sitting in a queue behind thousands of lower-priority items.
There's also a direct financial and staffing cost. AppSec engineers are among the hardest security roles to hire and retain, and manual triage of low-value alerts is precisely the kind of repetitive, low-leverage work that drives burnout and attrition. A team that spends 60–70% of its cycle time dismissing noise has, in effect, halved its real capacity to fix code. On the vendor-management side, organizations running multiple overlapping scanners — a common state after years of point-tool acquisition — pay for redundant licenses that each produce their own uncorrelated alert stream, multiplying the fatigue without multiplying the coverage.
Can better prioritization actually fix alert fatigue without adding headcount?
Yes — the fix is prioritization by reachability and exploitability, not simply adding more people to read alerts. The lever that actually shrinks a backlog is reducing the denominator: instead of asking a human to review every pattern match, the system should determine which findings are reachable from an untrusted entry point, which dependencies are actually invoked at runtime, and which are already mitigated by existing controls — and only route the remainder to a human. Teams that adopt reachability-based triage typically report cutting the findings requiring manual review by 80–90%, because most flagged issues never turn out to sit on an exploitable path.
This isn't a headcount problem to begin with; it's a filtering problem. A five-person team can keep pace with a 200-service estate if the tool hands them 50 genuinely risky findings a quarter instead of 3,000 undifferentiated ones. The organizations that break free from appsec alert fatigue are the ones that replace "scan everything, flag everything, rank by CVSS" with "scan everything, verify reachability, rank by exploitability" — collapsing the queue at the source rather than trying to process it faster.
How Safeguard Helps
Safeguard was built around the premise that appsec alert fatigue is a triage-architecture failure, not a discipline failure — so we designed the pipeline to filter before it alerts, not after.
- Reachability-first analysis. Instead of flagging every dependency that contains a CVE, Safeguard traces whether the vulnerable function is actually reachable from your application's entry points and call graph. If a vulnerable package is imported but the flagged function is never invoked, it's deprioritized automatically instead of landing in the same queue as an exploitable path.
- Provenance-aware SCA. Because Safeguard tracks the full software supply chain — build provenance, dependency origin, and package integrity — findings come with context: was this dependency pulled from a trusted, signed source, has it changed unexpectedly, is it part of a known compromised release. That context lets teams distinguish "routine CVE in an unused function" from "a dependency that just started behaving suspiciously," instead of treating both as generic alerts.
- Deduplication and finding memory. Safeguard tracks finding identity across scans and code changes, so a previously triaged, deprioritized, or suppressed issue doesn't reappear as new work every time a dependency bumps or a scan engine updates. Decisions persist; the backlog doesn't regenerate itself.
- Risk-ranked, not severity-labeled, output. Rather than surfacing a flat list sorted by CVSS, Safeguard ranks findings by a composite of reachability, exploitability, exposure (internet-facing vs. internal), and blast radius — so the alerts that reach an engineer's queue are the ones actually worth their attention today.
- Migration-ready ingestion. Teams moving off Veracode or consolidating multiple scanners can import existing finding histories, so the transition itself doesn't produce a fresh wave of "new" alerts for issues already triaged under the old tool.
The result is a queue measured in dozens, not thousands — sized to what a real team can act on every week, not what a scanner can theoretically detect. Breaking free from appsec alert fatigue doesn't mean scanning less. It means only asking a human to look at the findings that were actually worth finding.