Vulnerability processing in Fleet detects vulnerable software installed on your hosts. To see what software vulnerability processing covers, check out the [Coverage section on the Vulnerability processing doc](#coverage).
Vulnerable software can have one or more vulnerabilities (CVEs).
For Fleet Premium users, each CVE includes its CVSS base score (reported by the [National Vulnerability Database](https://nvd.nist.gov/)), probability of exploit (reported by [FIRST](https://www.first.org/epss/)), and whether or not their is a known exploit in the wild (reported by the [Cybersecurity & Infrastructure Security Agency](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)).
As of right now, only app names with all ASCII characters are supported. Apps with names featuring non-ASCII characters, such as Cyrillic, will not generate matches.
When upgrading to Fleet 4.7.0 or later, vulnerability processing is automatically enabled if
vulnerability processing and software inventory are not explicitly disabled.
If you explicitly disabled vulnerability processing, and now would like to enable this feature, first enable the software inventory feature by setting the following app config:
Fleet runs vulnerability downloading and processing via internal scheduled cron job. This internal mechanism is very useful
for frictionless deployments and is well suited for most use cases. However, in larger deployments,
where there can be dozens of Fleet server replicas sitting behind a load balancer, it is desirable to manage vulnerability processing externally.
The reasons for this are as follows:
- lower resource requirements across the entire Fleet server deployment (as vulnerability processing requires considerably more resources than just running Fleet server alone)
- more control over scheduling constraints (only process during windows of low utilization, etc.)
It is possible to limit vulnerability processing to a single [dedicated host](https://fleetdm.com/docs/deploying/configuration#current-instance-checks), by setting
`current_instance_checks` to `no` but still run one Fleet server as `yes`, but the drawback here is still having to dedicate resources
for this single host 24/7. The Fleet binary has a command which handles the same vulnerability processing, but will exit (successfully with 0) on completion. Using this sub-command we can delegate vulnerability processing
For example, when running a development instance of Fleet on an Apple Macbook Pro with 16 cores, matching 200,000 CPEs against the CVE database will take around 10 seconds and consume about 3GBs of RAM.
There are several steps that go into the vulnerability detection process. In this section we'll dive into what they are and how it works.
The process has different parts that are more error-prone than others. Each OS and each application developer and maintainer can (and do) have their own way of defining each part of their app. Some Linux distributions are very strict, but each distribution handles things differently.
The whole pipeline exists to compensate for these differences, and it can be divided in two sections:
This is the first step into normalizing data across platforms, as we try to get all the same data for all different types of software we detect vulnerabilities on.
Ingestion can be resource hungry, both on the hosts and the Fleet server. A lot of work has gone into reducing the resources needed, and it's still ongoing.
### Translating to CPE
With a somewhat normalized list of software, in order to search CVEs for it, we need to derive a [CPE](https://en.wikipedia.org/wiki/Common_Platform_Enumeration) from the vendor, name, version, and OS.
As described briefly above, we do this by translating the NVD database of CPEs into a [sqlite database that helps Fleet do the lookup of CPEs very quickly](https://github.com/fleetdm/nvd).
If the CPE is too vague, the extreme case being all parts are `*`, all CVEs will match. You want a very specific CPE, but not too specific that a small error would make it not match a CVE (false negative).
If we look at the [official releases](https://github.com/tmux/tmux/releases/tag/3.2a) the version we get is the same as the one listed. This means that it'll be easy to map it to a CPE that will accurately represent the software.
Now let's look at Chrome on macOS:
```
osquery> select name, bundle_version from apps where name like '%Chrome%';
+-------------------+----------------+
| name | bundle_version |
+-------------------+----------------+
| Google Chrome.app | 4758.102 |
+-------------------+----------------+
```
Now things start to get slightly more tricky. We have to remove the `.app` suffix from the name, then derive the first word as the vendor and the second as the app name. We could use `bundle_name` for the app name, but nothing stops the app developer of adding the vendor to `bundle_name`, so a similar parsing would have to happen.
These are two illustrative examples. The reality is that there is no map or list of all the software available and how it's presented in each platform, so the "software to CPE" translation process is going to be evolving constantly.
In order to improve the accuracy of matching software to CPEs, CPE translations rules are added for known cases where matching fails.
`server/vulnerabilities/cpe_translations.json` contains these rules and is included in the [NVD release](https://github.com/fleetdm/nvd/releases/latest).
##### Example: `ruby@2.7` installed via `homebrew`
The following CPE translation rule is used to reduce false positives when ruby is installed via homebrew.
This is needed because ruby is commonly included in the title in the CPE database.
This rule matches the software name `ruby` matching a regular expression pattern and installed using `homebrew`.
When searching for CPEs, the specifed `product` and `vendor` will be added to the filter critera.
| `software` | array[CPE Translation Software] | The CPE translation software match criteria. |
| `translation` | array[CPE Translation] | The CPE translation. |
##### CPE Translation Software (object)
The CPE translation software match criteria. Used to match software collected from hosts. Fields are are AND'd together. Values inside each field are OR'd together.
| Name | Type | Description |
| --- | --- | --- |
| `name` | array[string] | The software name to match. Enclose within `/` to specify a regular expression pattern. |
| `bundle_identifer` | array[string] | The software bundle identifier (MacOS apps only) to match. Enclose within `/` to specify a regular expression pattern. |
| `source` | array[string] | The software source to match. Enclose within `/` to specify a regular expression pattern. |
##### CPE Translation (object)
The CPE translation. Used to match CPEs in the CPE database. Fields are are AND'd together. Values inside each field are OR'd together.
| Name | Type | Description |
| --- | --- | --- |
| `product` | array[string] | The CPE product. |
| `vendor` | array[string] | The CPE vendor. |
| `target_sw` | array[string] | The CPE target software. |
Once we have a good CPE, we can match it against the CVE database. We download the data streams locally and match each CPE to the whole list. The matching is done using the [nvdtools implementation](https://github.com/facebookincubator/nvdtools).