Safeguard
Application Security

What is a False Positive in Security Scanning

False positives waste security team hours flagging vulnerabilities that aren't actually exploitable. Here's how to spot, measure, and reduce them.

Bob
Application Security Engineer
Updated 7 min read

A false positive in vulnerability scanning is an alert that flags a security issue that isn't actually exploitable, or isn't present at all, in the way the scanner claims. A scanner might report that your application uses log4j-core 2.14.1 and is therefore vulnerable to Log4Shell (CVE-2021-44228), when in reality your code never touches the JndiManager class the exploit depends on. The CVE is real. The version match is real. The exploitability in your specific deployment is not. Multiply that pattern across a monorepo with tens of thousands of transitive dependencies, and a single scan can return thousands of findings that look identical in severity but differ enormously in actual risk. Security teams that can't tell the two apart end up either drowning in triage work or, worse, tuning out the noise entirely and missing the handful of findings that matter. The same false positive and false negative tradeoff shows up outside application scanning too — network security tooling like IDS/IPS and firewalls faces an identical signal-versus-noise problem, just with packets instead of packages.

What is a false positive in vulnerability scanning?

A false positive is a scanner finding that doesn't reflect real, exploitable risk in the running application. This differs from a false negative, which is a vulnerability the scanner misses entirely. Most false positives in software composition analysis (SCA) come from version-matching logic: the tool sees that a manifest file lists lodash@4.17.15 and flags every CVE ever published against any 4.17.x release, without checking whether the vulnerable function is ever called, whether the package is bundled into a shipped artifact, or whether it's a devDependency that never reaches production. Static application security testing (SAST) tools produce a parallel version: they flag a pattern like string concatenation into a SQL query as a potential injection vulnerability even when the input is a hardcoded enum value that a user can never influence.

Why do SCA and SAST tools generate so many false positives?

SCA and SAST tools over-flag because most of them match on presence, not on reachability. A traditional SCA scanner parses a lockfile or SBOM, cross-references package names and version ranges against a CVE feed like the NVD, and emits a finding for every match — regardless of whether the vulnerable function is ever invoked by the application. This is fast and cheap to compute, which is why it became the industry default, but it treats "this package exists somewhere in the dependency tree" as equivalent to "this application is exploitable." A 2023 example: CVE-2023-4863, a heap buffer overflow in libwebp, triggered alerts across huge swaths of the npm and Python ecosystems because so many packages pulled in libwebp transitively for image processing — including plenty of backend services that never decode untrusted, attacker-supplied WebP images at all. The CVE was severe (CVSS 8.8) and correctly identified in the dependency graph, but for a large share of the flagged applications, the actual attack surface didn't exist.

What's a concrete example of a false positive in practice?

A concrete example is a Java service flagged for CVE-2021-44228 (Log4Shell) that imports log4j-core solely for local file-based logging and never constructs a logger with attacker-controlled input passed through JNDI lookups. The scanner correctly identifies the vulnerable dependency version. What it doesn't check is whether the vulnerable code path — the JndiLookup class being invoked with untrusted data — is actually reachable from any entry point in the application. Another common example: a Python project flagged for a deserialization vulnerability in PyYAML because it imports the library, when the code only ever calls yaml.safe_load() and never touches the vulnerable yaml.load() function the CVE describes. In both cases, patching immediately isn't wrong, but treating the finding as equally urgent as a genuinely reachable critical vulnerability misallocates a team's limited remediation hours.

How much does false positive triage actually cost a security team?

False positive triage costs security teams the majority of the time they spend on vulnerability management, because someone still has to manually verify each finding before it can be dismissed or escalated. If a scan of a mid-sized monorepo returns 2,000 dependency findings and only 150-300 correspond to reachable, exploitable code paths, an engineer or AppSec analyst has to spend time — often 10-20 minutes per finding when context is unclear — reading changelogs, checking call graphs by hand, and pinging application owners just to close out findings that were never real risk. That triage tax is also why vulnerability backlogs grow rather than shrink: teams start batching low-confidence findings into a "later" bucket, and "later" becomes never. When a genuinely critical, reachable vulnerability lands in that same queue, it's competing for attention with hundreds of items that already trained the team to expect noise.

What's the difference between a false positive and an unpatched risk that just looks low priority?

The difference is exploitability, not severity score. A finding with a CVSS score of 9.8 can be a false positive if the vulnerable function is unreachable, dead code, or stripped out at build time, while a CVSS 6.5 finding can be genuinely critical if it sits on an internet-facing endpoint that accepts unauthenticated input. Relying on CVSS alone to prioritize is one of the most common reasons teams misroute their effort: CVSS describes the theoretical worst case for a vulnerability in isolation, not whether your specific application exposes the conditions needed to trigger it. A false positive isn't "low severity" — it's zero real-world severity in your environment, and it needs a different label than a true finding that's merely lower priority.

How can teams reduce false positives without introducing false negatives?

Teams reduce false positives by adding reachability analysis on top of version matching, not by loosening detection thresholds. Reachability analysis builds a call graph from your application's actual entry points down through its dependencies and checks whether the specific vulnerable function in a flagged CVE is ever invoked, directly or transitively, by code that runs in production. This is different from simply suppressing findings based on age or ignoring devDependencies, both of which risk hiding real negatives — the same principle that separates a well-tuned false positive and false negative balance in network security from an IDS that's simply been told to stop alerting. Combining reachability with accurate SBOMs (so you know exactly what's shipping, including transitive and container-layer dependencies) and exploit-maturity signals (is there a public PoC, is it being actively exploited per CISA KEV) gives teams a ranked list where the top items are both severe and actually reachable — rather than a flat list where a false positive and a critical live exploit path get the same red badge.

How Safeguard Helps

Safeguard's Griffin AI engine runs reachability analysis against every dependency finding, tracing call graphs from real application entry points to determine whether a flagged vulnerable function is actually invocable in your build, and automatically downgrades or suppresses findings that aren't — cutting the triage queue down to the vulnerabilities that represent genuine exposure. Safeguard generates and ingests SBOMs across source, container, and CI/CD layers so reachability decisions are made against a complete, accurate picture of what's actually shipping, not just a top-level manifest. For findings confirmed as reachable and exploitable, Safeguard opens auto-fix pull requests with the minimum safe version bump or patch, so remediation doesn't require a separate manual triage-to-fix handoff. The result is a vulnerability backlog that reflects real risk instead of scanner noise.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.