AI and Automation

Why Vulnerability Scanners Report So Many False Positives

22 September 2026 8 min read

Every security team that has triaged a scan export knows the pattern: a run comes back with forty findings, thirty of them get closed within the hour as not applicable, and the remaining ten still need someone to log into a box before a ticket can be opened. This is not a defect in any single scanner. It is a structural consequence of how remote and host based checks gather evidence in the first place. Four mechanisms account for nearly all of it, and each one can be tested directly instead of debated.

Four Structural Causes Behind Most False Positives

Before assigning a finding to an engineer, it helps to know which of these four buckets it falls into, because the verification step is different for each one.

Banner and Version String Matching

Most unauthenticated checks read a service banner, an HTTP Server header, an SSH version string, an SMTP EHLO response, and match it against a CPE (Common Platform Enumeration) entry. A banner is a string the vendor chose to expose, not a cryptographic attestation of what code is running. Administrators routinely edit or suppress banners (ServerTokens Prod in Apache, a custom SSH Banner directive) for reasons that have nothing to do with the vulnerability being tested. When the string does not match cleanly, some scan engines fall back to the closest known pattern, which produces a plausible but wrong CPE and, downstream, a CVE that does not apply to the actual build.

Backported Security Patches

A vendor or distribution maintainer fixes a CVE by porting the patch into an older release branch without changing the upstream version number that a banner or package name reports. The scanner still sees “OpenSSH 7.4” and flags every CVE ever filed against 7.4, even though the specific flaw was closed eighteen months ago in a maintenance update. This single mechanism is responsible for a large share of the false positives reported against long term support Linux distributions.

Unauthenticated Guessing

Without valid credentials, a scanner cannot read the package manager’s database, a registry key, or a build manifest. It infers the software stack from network responses: response headers, error page templates, favicon hashes, default file paths. Inference is probabilistic by design. A host running a hardened, custom-compiled build of a package will often get misclassified as a stock build with known holes, because the scanner has no way to ask the operating system directly what is installed.

Unreachable or Dead Code Paths

A vulnerability scanner typically checks for the presence of a vulnerable component, not whether an attacker can actually reach the vulnerable function. A PHP file with an injection flaw that is never included by any router, a library loaded but never called with attacker-controlled input, a feature compiled in but gated behind a license flag that is off, all of these produce a “vulnerable version detected” result with zero real attack surface. Static analysis tools have the same problem in reverse: they see the code and cannot always tell if it executes.

Why Distro Backports Break Version Comparison Logic

Red Hat, Debian, and Ubuntu each maintain long term support branches that receive security fixes for years after the upstream project has moved to a different major version. The distribution package version keeps the upstream base (for example 1.1.1k for OpenSSL on a given RHEL point release) and appends a distro-specific revision suffix that records the backport, such as 1.1.1k-7.el8_9. A scanner comparing only the semantic version against the National Vulnerability Database’s “fixed in” field sees 1.1.1k, concludes the host predates the fix, and raises a critical finding for a CVE that was closed months earlier.

The practical fix is to stop trusting the semantic version alone and check the vendor’s own advisory tracking:

Distribution Command to inspect patch history Authoritative source to cross-check
RHEL / CentOS / Alma / Rocky rpm -q --changelog <package> | grep -i CVE-XXXX-YYYYY Red Hat Security Advisories (errata database)
Debian apt-get changelog <package> | grep -i CVE Debian Security Tracker
Ubuntu dpkg -l <package> then check the version suffix against USN Ubuntu Security Notices (USN)
SUSE rpm -q --changelog <package> SUSE CVE database

If the changelog entry references the CVE ID and predates the scan date, the finding is a backport false positive and should be closed with that changelog line attached as evidence, not just a note saying “verified false positive.”

Inactive Services, Disabled Modules, and Compensating Controls the Scanner Never Sees

A network scan enumerates open ports and responding services. It does not know that the reachable service is disabled at the application layer, that the vulnerable module is present on disk but never loaded, or that a WAF rule strips the exact parameter an exploit needs. Three checks resolve most of these:

  • Process state: systemctl is-active <service> and ss -ltnp confirm whether the port is actually bound by the flagged binary right now, not just reachable through some proxy or load balancer default page.
  • Module load state: for Apache, grep the loaded configuration (apachectl -M) rather than the presence of a .so file in /etc/httpd/modules. A commented-out LoadModule line means the vulnerable code path never executes.
  • Compensating controls: a WAF rule, a network ACL that restricts the port to an internal jump host, or an authentication proxy in front of the vulnerable endpoint changes exploitability without changing the underlying version. These need to be recorded against the asset, not just the finding, so the same suppression logic applies the next time the same CVE shows up on the same host.

This is where asset context earns its keep: a finding tied to a host record that already carries its network exposure, its compensating controls and its business criticality can be triaged automatically against a rule set instead of requiring a fresh manual lookup every scan cycle, which is the role an asset inventory module plays when it is kept current.

Plugin Quality Differences Between Scanners on the Same Host

Point two different scanners at the same host and it is common to get two different verdicts on the same CVE. The check logic is not standardized across vendors: one plugin might match on version string alone, another might require a specific file hash, a third might attempt a safe proof-of-concept request and only flag on a successful response.

Check style What it verifies Typical false positive rate
Banner or CPE match only Reported version string High
Authenticated package query Installed package and patch revision Low, unless backport metadata is ignored
Safe active probe Actual response to a crafted, non-destructive request Lowest, but not available for every CVE
Static file or hash check Presence of a specific vulnerable file Medium, misses reachability

Running seventeen scanners in parallel, as many enterprise environments now do across network, web application, container and cloud posture tools, multiplies this problem before it solves it: the same underlying flaw arrives as five separate tickets with five confidence levels and five different pieces of evidence attached. Deduplication logic has to reconcile the CVE identifier, the asset identity and the check method before an analyst ever sees the finding, otherwise triage time goes up rather than down. This is the specific job of a scanner integration layer: normalize disparate plugin output into one record per real-world vulnerability instead of one record per tool.

How to Confirm or Dismiss Each Cause: Concrete Checks

A repeatable decision path beats an ad hoc argument in a ticket thread. The following order clears most findings in minutes:

  1. Reachability first. ss -ltnp or netstat -tulnp confirms the port is bound by the reported service right now. If it is not listening, close as a stale scan artifact and rescan.
  2. Authenticated version check. Pull the actual installed package version with rpm -qa, dpkg -l, or the platform’s equivalent, rather than trusting the banner. A mismatch between banner and package database points to a hardened or custom build.
  3. Changelog cross-reference. Check the distribution’s changelog for the specific CVE ID, as shown in the backport table above. This alone resolves most RHEL and Ubuntu long term support false positives.
  4. Module or feature flag state. Confirm the vulnerable code path is actually loaded (module list, running configuration, feature flag state), not merely present on disk.
  5. Safe exploit attempt where available. For web application findings with a documented non-destructive proof-of-concept, a single controlled request settles the question faster than a document review.

A useful decision rule for triage backlogs: if CVSS is 7.0 or higher and an authenticated check confirms the vulnerable version with no compensating control on file, escalate within the current sprint; if any single confirmation step above fails, close with the specific evidence attached rather than a generic “false positive” label, because the next scan will raise the same finding again without that context.

What Context a Scanner Would Need to Be Right

Put together, the four causes point to the same missing ingredient: ground truth about the actual runtime state of the host, not an inference from the outside. A scanner would need shell or API level access to the package manager, the process table, the loaded application configuration, and a record of prior triage decisions for that exact asset and CVE pair. Few scanners are given all of that, and none of them retain triage history between runs on their own.

This is the gap that automated validation and re-testing close. Platforms that automate this phase, such as SITEY, re-test the specific finding against the live host instead of trusting a patch command’s exit code, and carry forward the compensating controls and prior dismissal reasons so the same false positive is not re-litigated every scan cycle. The validation step matters more than the initial detection: a scanner that finds everything and confirms nothing just moves the manual work downstream instead of removing it. Feeding scan output through a triage layer that checks reachability, authenticated version state and changelog data before a finding reaches an engineer, the kind of step an AI triage module performs, is what turns forty raw findings into ten that are worth a human’s time. Closing the loop with an automatic re-test after remediation, rather than trusting a ticket status change, is what a retest and closure stage is for, and it is the only way to confirm a fix actually removed the exposure rather than just changed a banner string.

About SITEY

SITEY is an autonomous vulnerability management platform. It discovers, validates, prioritizes, remediates and re-tests vulnerabilities through an eight-phase automated pipeline, unifying output from 17 integrated scanners. SITEY is self-hosted: it runs in your own infrastructure and your findings are stored there. Outbound connections are limited to licence activation and the optional services you enable, such as an AI provider, CVE enrichment and patch catalogues. Pricing is 599 USD per month or 5,999 USD for a perpetual lifetime license. See pricing or how the platform works.

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing