Finds the software a host runs and looks each version up against known advisories.
Most servers that get broken into were not attacked cleverly. They were running a version of something with a published flaw, and somebody scanning the whole internet found them. The versions are not secret: a web server, PHP, SSH and most mail software announce themselves to anyone who connects. This scan reads what yours announces and looks each version up.
Enter a host name or public IP address. The scan connects once to each of a short list of ports, reads the greeting or the HTTP headers, works out the product and version, and reports every advisory in our signature database that covers that version, plus any version that has passed its end of security support.
Nothing is exploited and nothing is guessed. The scan sends one connection per port and, on a web port, one request for the home page — the same bytes a browser sends. That makes it safe to run against production, and it also sets the limit of what it can prove: a match means the version announced is one an advisory covers, not that the flaw is reachable on your build.
A scanner that has no account on your server cannot read the package list, so it does the only thing left: it listens to what your software says about itself. A web server puts its name and often its version in the Server header of every response. PHP adds an X-Powered-By line unless told not to. SSH, SMTP and FTP daemons send a greeting before a single byte is typed at them. None of that is a leak in the dramatic sense. It is how the protocols were designed, and a browser receives it on every page load.
The scan reads those strings, works out a product and a version, and looks the version up in a database of published advisories. That is the whole method, and it is the method behind the internet-wide scanning that finds most compromised servers: somebody indexes who is running what, an advisory is published, and the list of targets already exists.
Knowing this tells you how to read the result. The scan proves what your server announced. It does not prove the flaw is present, because the same version number can describe a build with the fix and a build without it.
A signature is one record: a product, the version ranges a published advisory covers, the CVE identifiers, what an attacker gains, what the owner should do, and a link to the entry in the National Vulnerability Database so the claim can be checked rather than believed. Records live one file per product family, so adding one changes nothing else.
Version ranges are half-open: a version matches when it is at or above the version a flaw was introduced in, and below the version that fixed it. A single record usually carries several ranges, because a vendor fixes the same flaw in every supported branch on the same day. The flaw in PHP's CGI handler published in 2024 was fixed in 8.1.29, 8.2.20 and 8.3.8 together, and a record that listed only one of those would miss two thirds of the affected servers.
Three routes bring a record in. By hand, from a vendor advisory, when something matters enough to add the day it is published. In bulk from the NVD feed, which is read by a maintenance script from a shell and never from a visitor's request, so a slow or missing feed can never affect a scan. And from the end-of-life list, which needs no CVE at all: when a branch stops receiving security fixes, every flaw found in it from that date onwards stays unfixed, which is worth reporting on its own.
Every record is validated before it ships: the identifier has to be well formed, the severity has to be one of the five levels, each CVE has to look like a CVE, each reference has to be https, no range may be open at both ends, and the product has to be one the scanner can actually detect. A record for software nothing can recognize would never fire, so it is rejected rather than quietly carried. The test suite runs the validator over every file, so a malformed signature fails the build instead of a scan.
| Field | What it holds | Why it is checked |
|---|---|---|
| id | SXV-PHP-0001 and so on, unique across the database | Two records with one identifier would collide in a report |
| product | The canonical name, such as apache httpd | It must match a product the fingerprinter can detect |
| affected | One or more ranges of introduced and fixed versions | A range open at both ends would match every version ever released |
| cves | The CVE identifiers, which become links to NVD | So a reader can check the claim at its source |
| severity and cvss | One of critical, high, medium, low, info, and the score | The score rates the flaw in the abstract, not your exposure |
| fix | What the owner should do, in a sentence | A finding without an action is a complaint |
The honest weakness of version matching is backporting. When a flaw is found in PHP, Ubuntu and Red Hat do not ship the new upstream release to a stable system. They apply the fix to the version already there and bump their own packaging number, so a patched server can keep announcing 8.1.2 for years. Match on the upstream number alone and you report a flaw that was fixed eighteen months ago.
So the scan looks at the shape of the version string. A suffix such as 1ubuntu2.14 or el9 says a distribution built it, and the match drops from likely to possible with the reason written into the finding. Confirm it from the inside, where the answer is certain: ask your package manager what is installed and read the vendor's advisory for that package rather than the upstream project's.
The error runs the other way too. A server that hides its versions produces a clean report and may be years out of date. Suppressing version strings is sound practice and makes this kind of scan useless against you, which is rather the point of it. Patch levels are answered from your own inventory.
The finding is the easy part. What fails in most organizations is the loop after it, so run the result into one rather than filing it.
No. It opens one connection to each port and, on a web port, asks for the home page once. No exploit is attempted, no password is tried, no parameter is altered and no hidden path is guessed. Everything it reads is what your server tells any visitor. It is safe to run against production.
Both can be true. Ubuntu, Debian and Red Hat fix flaws by patching the version they already ship, so PHP 8.1.2 on Ubuntu may contain a fix that upstream released in 8.1.29 while still calling itself 8.1.2. Where the version string shows that packaging we mark the match as possible rather than likely. Confirm with your package manager: rpm -q or dpkg -l, then the vendor's advisory for that package.
Because it is unauthenticated and non-intrusive, which is deliberate. A scanner that logs in can read the installed package list and is far more accurate; one that sends exploits can confirm a finding but may also break what it is testing. This tool shows what a stranger on the internet can learn about you in a few seconds, which is the exposure worth knowing.
It means nothing announced a version an advisory covers. A host that hides its versions gives this scan very little to work with, which is good practice and a weak test. Patch levels are answered properly from your own inventory, not from outside.
Each one records a product, the version ranges a published advisory affects, the CVE identifiers and a link to the entry in the National Vulnerability Database so you can check it yourself. They are added by hand from vendor advisories and in bulk from the NVD feed, and every record is validated before it ships. The guide below sets out the format and the process.
Only one you own or are authorized to test, which you confirm before the scan runs. Private, loopback and cloud-metadata addresses are refused, and so are names that point to them.