Vulners Linux Audit API for Host Vulnerability Detection: Manual Auditing, Python Scripting and Licensing

ID AVLEONOV:C161660A7999856B2D4E2D00187C74F6
Type avleonov
Reporter Alexander Leonov
Modified 2021-02-11T23:31:01


Hello everyone! This episode will be about Vulners Linux Audit API, which allows you to detect vulnerabilities on a Linux host knowing only the OS version and installed packages. I had a similar post about this 4 years ago, but some details have changed, so I came back to this topic.

Manual Audit

The easiest way to try Vulners Linux Audit capabilities, that even doesn’t require registration, is to go to <> where you can specify the OS type, OS version and the output of the command for RedHat and Debain based Linux distributions.

Vulners supports nearly all popular Linux distributions:

For RedHat (RPM) based distributions, you can get OS version using

$ cat /etc/redhat-release
CentOS Linux release 8.3.2011

and list installed packages using

rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n'

For Debain (DEB) based distributions, you can get version using

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic

and list installed packages using

dpkg-query -W -f='${Status} ${Package} ${Version} ${Architecture}\n'|awk '($1 == "install") && ($2 == "ok") {print $4" "$5" "$6}'

For example, I've added packages for Ubuntu 18.04:

And got the results (packages and vulnerabilities in the form of USN bulletins):

The vulnerabilities are clickable:

What are the limitations? If you installed software from source codes or built the package yourself with some random version, of course, Vulners will not find a vulnerability in this. It will also not detect a vulnerability if the application is running in a docker container.

Linux Audit API and python scripting

First of all, in order to use the Linux Scanner API, you must be a registered user.

Then you go to <> and generate an API key.

Choose the API scope and press save.

If you are new to Vulners, the license type will be free. It’s good enough for testing, I’ll add a few words about licensing later.

So, here is the script. Nothing special. List of packages in the same format as in Manual Audit, data dictionary with OS type and version, authentication token, one post request.

import requests
import json

packages = '''accountsservice 0.6.45-1ubuntu1 amd64
acl 2.2.52-3build1 amd64
acpid 1:2.0.28-1ubuntu1 amd64
adduser 3.116ubuntu1 all
apparmor 2.12-4ubuntu5.1 amd64
apport 2.20.9-0ubuntu7.9 all
apport-symptoms 0.20 all
apt 1.6.12 amd64
apt-utils 1.6.12 amd64

package_list = packages.split("\n")
token = "###TOKEN###"
data = {"os": "ubuntu", 
        "version": "16.04", 
        "package": package_list, 
        "apiKey": token}
response ='', 
print(json.dumps(response.json(), indent=4))

So in output I get the same vulnerabilities as in Manual Audit. Security bulletin vulnerabilities are grouped by package name. The most interesting is that we see the providedVersion which is less then bulletinVersion, so it can be verified manually. You can also see the list of related CVEs and a command for fixing.

    "result": "OK",
    "data": {
        "packages": {
            "snapd 2.42.1+18.04 amd64": {
                "USN-4424-1": [
                        "package": "snapd 2.42.1+18.04 amd64",
                        "providedOSName": "ubuntu",
                        "matchedOSName": "ubuntu",
                        "bulletinOSName": "Ubuntu",
                        "providedOSVersion": "16.04",
                        "bulletinOSVersion": "16.04",
                        "providedVersion": "2.42.1+18.04",
                        "bulletinVersion": "2.45.1ubuntu0.2",
                        "providedPackage": "snapd 2.42.1+18.04 amd64",
                        "bulletinPackage": "UNKNOWN",
                        "operator": "lt",
                        "bulletinID": "USN-4424-1",
                        "cvelist": [
                        "cvss": {
                            "score": 4.6,
                            "vector": "AV:L/AC:L/Au:N/C:P/I:P/A:P"
                        "fix": "sudo apt-get --assume-yes install --only-upgrade snapd"

So, is it free?

I often hear from employees of large companies that they use Vulners for Vulnerability Management because it’s toll free. Well, strictly, it is not.

In the footer of each page there is a link to EULA. According to it, it’s free for personal education or research use. If you use Vulners at work to monitor your infrastructure or to get information about vulnerabilities, this is a commercial usage and you have to pay.

How much? It’s better to request the latest details from But currently the price starts from €150/month WITHOUT API usage and from €500/month for 10000 API calls. For €1000/month you can use Vulners API with no restrictions.

Is this a lot? 6000 €/year (500 €/month) is about twice as much as the price of Nessus Professional. But comparing with other enterprise Vulnerability Management solutions, it’s not really so much. For example, it’s the price of for only 160 hosts. With Vulners Linux API and some optimization, it would be possible to cover MUCH more hosts and easily asses them daily.

One way to optimize is not to make a separate request for every host, but to collect all the packages that are used in your infrastructure for the OS version and make one request to collect related vulnerabilities. This optimization is ok, because it doesn’t make additional load on Vulners servers.

What if you want to use Vulners API for commercial goals, but don’t need so many API calls? Well, strictly, such using without commercial license would be a violation. But you will not be banned if you use <1000 request per month. And Vulners Team doesn’t ban such usage during the PoC, etc. Everything is discussable. But if you can pay, there is no reason you shouldn’t. Vulners is a small self-financing startup that does a lot of work with very limited resources. Commercial licenses really help to pay servers and motivate the team to move on. 😉