Welcome to CVE Binary Tool’s documentation!

The CVE Binary Tool helps you determine if your system includes known vulnerabilities. You can scan binaries for a number of common, vulnerable components (openssl, libpng, libxml2, expat and others), or if you know the components used, you can get a list of known vulnerabilities associated with a list of components and versions.

CVE Binary Tool quick start / README

Build Status codecov Gitter On ReadTheDocs On PyPI Code style: black Imports: isort CII Best Practices OpenSSF Scorecard

The CVE Binary Tool is a free, open source tool to help you find known vulnerabilities in software, using data from the National Vulnerability Database (NVD) list of Common Vulnerabilities and Exposures (CVEs) as well as known vulnerability data from Redhat, Open Source Vulnerability Database (OSV), Gitlab Advisory Database (GAD), and Curl.

CVE Binary Tool uses the NVD API but is not endorsed or certified by the NVD.

The tool has two main modes of operation:

  1. A binary scanner which helps you determine which packages may have been included as part of a piece of software. There are 360 checkers. Our initial focus was on common, vulnerable open source components such as openssl, libpng, libxml2 and expat.

  2. Tools for scanning known component lists in various formats, including .csv, several linux distribution package lists, language specific package scanners and several Software Bill of Materials (SBOM) formats.

It is intended to be used as part of your continuous integration system to enable regular vulnerability scanning and give you early warning of known issues in your supply chain. It can also be used to auto-detect components and create SBOMs.

What CVE Binary Tool does when it runs:

Diagram of cve-bin-tool's workflow, described in text with more detail below.

  1. Download CVE Data (from NVD, Redhat, OSV, Gitlab, and Curl).

    • This happens once per day by default, not every time a scan is run.

    • On first run, downloading all data can take some time.

  2. Create/read a component list. There are two modes of operation:

    1. Creates a component list (including versions) using a combination of binary checkers and language component lists (such as python’s requirements.txt).

    2. Read SBOM (use an existing component list in a standardized Software Bill of Materials format.)

  3. Create CVE List

    • This looks up all components found or read from an existing bill of materials and reports back any known issues associated with them

  4. Include triage/additional data

    • There are several options for adding triage/notes, information from previous reports to track vulnerability change over time, or known fix data

  5. Generate report in one or more formats (console, json, csv, html, pdf)

For more details, see our documentation or this quickstart guide

Installing CVE Binary Tool

CVE Binary Tool can be installed using pip:

pip install cve-bin-tool

If you want to try the latest code from the cve-bin-tool github or do development, you can also pip install --user -e . to install a local copy from a directory. The Contributor Documentation covers how to set up for local development in more detail.

Pip will install the python requirements for you, but for some types of extraction we use system libraries. If you have difficulties extracting files, you may want to look at our additional Requirements lists for Linux and Windows.

On first usage (and by default, once per day) The tool will download vulnerability data from a set of known vulnerability data sources. Due to reliability issues with NVD, as of release 3.3 we will be using our own NVD mirror at https://cveb.in/ by default rather than contacting NVD directly. If you wish to get data directly from the NVD servers you must provide your own NVD_API_KEY to use their API.

If you are using a release prior to 3.3 that does not use our mirror, please use an NVD_API_KEY as described above.

Output Options

The CVE Binary Tool provides console-based output by default. If you wish to provide another format, you can specify this and a filename on the command line using --format. The valid formats are CSV, JSON, console, HTML and PDF. The output filename can be specified using the --output-file flag.

You can also specify multiple output formats by using comma (‘,’) as separator:

cve-bin-tool file -f csv,json,html -o report

Note: You must not use spaces between the commas (‘,’) and the output formats.

The reported vulnerabilities can additionally be reported in the Vulnerability Exchange (VEX) format by specifying --vex command line option. The generated VEX file can then be used as a --triage-input-file to support a triage process.

If you wish to use PDF support, you will need to install the reportlab library separately.

If you intend to use PDF support when you install cve-bin-tool you can specify it and report lab will be installed as part of the cve-bin-tool install:

pip install cve-bin-tool[PDF]

If you’ve already installed cve-bin-tool you can add reportlab after the fact using pip:

pip install --upgrade reportlab

Note that reportlab was taken out of the default cve-bin-tool install because it has a known CVE associated with it (CVE-2020-28463). The cve-bin-tool code uses the recommended mitigations to limit which resources added to PDFs, as well as additional input validation. This is a bit of a strange CVE because it describes core functionality of PDFs: external items, such as images, can be embedded in them, and thus anyone viewing a PDF could load an external image (similar to how viewing a web page can trigger external loads). There’s no inherent “fix” for that, only mitigations where users of the library must ensure only expected items are added to PDFs at the time of generation.

Since users may not want to have software installed with an open, unfixable CVE associated with it, we’ve opted to make PDF support only available to users who have installed the library themselves. Once the library is installed, the PDF report option will function.

Configuration

You can use --config option to provide configuration file for the tool. You can still override options specified in config file with command line arguments. See our sample config files in the test/config

Auto-detection of components

CVE Binary tool attempts to do auto-detection of components using binary checkers, supported language component lists, and file extraction methods. The supported tools for auto-detection are listed below.

Binary checker list

The following checkers are available for finding components in binary files:

Available checkers

accountsservice

acpid

apache_http_server

apcupsd

apparmor

asn1c

assimp

asterisk

atftp

avahi

axel

bash

bind

binutils

bird

bison

bluez

boinc

botan

bro

bubblewrap

busybox

bwm_ng

bzip2

c_ares

capnproto

ceph

chess

chrony

civetweb

clamav

collectd

commons_compress

connman

coreutils

cpio

cronie

cryptsetup

cups

curl

cvs

darkhttpd

dav1d

davfs2

dbus

debianutils

dhclient

dhcpcd

dhcpd

dmidecode

dnsmasq

docker

domoticz

dosfstools

dotnet

dovecot

doxygen

dpkg

dropbear

e2fsprogs

ed

elfutils

emacs

enscript

exfatprogs

exim

exiv2

f2fs_tools

faad2

fastd

ffmpeg

file

firefox

flac

fluidsynth

freeradius

freerdp

fribidi

frr

gawk

gcc

gdal

gdb

gdk_pixbuf

gimp

git

glib

glibc

gmp

gnomeshell

gnupg

gnutls

go

gpgme

gpsd

graphicsmagick

grep

grub2

gstreamer

gupnp

gvfs

gzip

haproxy

harfbuzz

haserl

hdf5

heimdal

hostapd

hunspell

hwloc

i2pd

icecast

icu

iperf3

ipmitool

ipsec_tools

iptables

irssi

iucode_tool

iwd

jack2

jacksondatabind

janus

jhead

jq

json_c

kbd

keepalived

kerberos

kexectools

kodi

kubernetes

ldns

lftp

libarchive

libass

libbpg

libcoap

libconfuse

libcurl

libdb

libde265

libebml

libevent

libexpat

libgcrypt

libgd

libgit2

libheif

libical

libidn2

libinput

libjpeg

libjpeg_turbo

libksba

liblas

libmatroska

libmemcached

libmicrohttpd

libmodbus

libnss

libpcap

libraw

librsvg

librsync

libsamplerate

libseccomp

libsndfile

libsolv

libsoup

libsrtp

libssh

libssh2

libtasn1

libtiff

libtomcrypt

libupnp

libuv

libvips

libvirt

libvncserver

libvorbis

libvpx

libxslt

lighttpd

linux_kernel

lldpd

logrotate

lrzip

lua

luajit

lxc

lynx

lz4

mailx

mariadb

mbedtls

mdadm

memcached

micropython

minetest

mini_httpd

minicom

minidlna

miniupnpc

miniupnpd

moby

modsecurity

monit

mosquitto

motion

mpg123

mpv

msmtp

mtr

mupdf

mutt

mysql

nano

nasm

nbd

ncurses

neon

nessus

netatalk

netdata

netkit_ftp

netpbm

nettle

nghttp2

nginx

ngircd

nmap

node

ntfs_3g

ntp

ntpsec

open_iscsi

open_vm_tools

openafs

opencv

openjpeg

openldap

opensc

openssh

openssl

openswan

openvpn

p7zip

pango

patch

pcre

pcre2

pcsc_lite

perl

php

picocom

pigz

pixman

png

polarssl_fedora

poppler

postgresql

ppp

privoxy

procps_ng

proftpd

protobuf_c

pspp

pure_ftpd

putty

python

qemu

qpdf

qt

quagga

radare2

radvd

raptor

rauc

rdesktop

readline

rpm

rsync

rsyslog

rtl_433

rtmpdump

runc

rust

samba

sane_backends

sdl

seahorse

shadowsocks_libev

snapd

sngrep

snort

socat

sofia_sip

speex

spice

sqlite

squashfs

squid

sslh

stellarium

strongswan

stunnel

subversion

sudo

suricata

sylpheed

syslogng

sysstat

systemd

tar

tcpdump

tcpreplay

terminology

tesseract

thrift

thttpd

thunderbird

timescaledb

tinyproxy

tor

tpm2_tss

traceroute

transmission

trousers

ttyd

twonky_server

u_boot

udisks

unbound

unixodbc

upx

util_linux

varnish

vim

vlc

vorbis_tools

vsftpd

webkitgtk

wget

wireshark

wolfssl

wpa_supplicant

xerces

xml2

xscreensaver

xwayland

yasm

zabbix

zchunk

zeek

zlib

znc

zsh

zstandard

All the checkers can be found in the checkers directory, as can the instructions on how to add a new checker. Support for new checkers can be requested via GitHub issues.

Language Specific checkers

A number of checkers are available for finding vulnerable components in specific language packages.

Language Files supported
Dart pubspec.lock
Go Go.mod
Java pom.xml; JAR, WAR and EAR archives
JavaScript package-lock.json
Rust Cargo.lock
Ruby Gemfile.lock
R renv.lock
Swift Package.resolved
Python requirements.txt, PKG-INFO, METADATA; .whl and .egg files
Perl cpanfile

More information on language-specific checkers can be found in the CVE Binary Tool manual.

Supported Archive Formats

The following archive formats are currently supported by the auto-extractor:

Archive Format File Extension
zip .zip, .exe, .jar, .msi, .egg, .whl, .war, .ear
tar .tar, .tgz, .tar.gz, .tar.xz, .tar.bz2
deb .deb, .ipk
rpm .rpm
cab .cab
apk .apk
zst .zst
pkg .pkg

Additional Requirements

To use the auto-extractor, you may need the following utilities depending on the type of supported archive formats you need to extract.

The utilities below are required to run the full test suite on Linux:

  • file

  • strings

  • tar

  • unzip

  • rpm2cpio

  • cpio

  • ar

  • cabextract

Most of these are installed by default on many Linux systems, but cabextract and rpm2cpio in particular might need to be installed.

On windows systems, you may need:

  • ar

  • 7z

  • Expand

  • pdftotext

Windows has Expand installed by default, but ar and 7z might need to be installed. If you want to run our test-suite or scan a zstd compressed file, We recommend installing this 7-zip-zstd fork of 7zip. We are currently using 7z for extracting jar, apk, msi, exe and rpm files. To install ar you can install MinGW (which has binutils as a part of it) from here and run the downloaded .exe file.

If you get an error about building libraries when you try to install from pip, you may need to install the Windows build tools. The Windows build tools are available for free from https://visualstudio.microsoft.com/visual-cpp-build-tools/

If you get an error while installing brotlipy on Windows, installing the compiler above should fix it.

pdftotext is required for running tests. (users of cve-bin-tool may not need it, developers likely will.) The best approach to install it on Windows involves using conda (click here for further instructions).

You can check our CI configuration to see what versions of python we’re explicitly testing.

Limitations

This scanner does not attempt to exploit issues or examine the code in greater detail; it only looks for library signatures and version numbers. As such, it cannot tell if someone has backported fixes to a vulnerable version, and it will not work if library or version information was intentionally obfuscated.

This tool is meant to be used as a quick-to-run, easily-automatable check in a non-malicious environment so that developers can be made aware of old libraries with security issues that have been compiled into their binaries.

The tool does not guarantee that any vulnerabilities reported are actually present or exploitable, neither is it able to find all present vulnerabilities with a guarantee.

Users can add triage information to reports to mark issues as false positives, indicate that the risk has been mitigated by configuration/usage changes, and so on.

Triage details can be re-used on other projects so, for example, triage on a Linux base image could be applied to multiple containers using that image.

For more information and usage of triage information with the tool kindly have a look here.

If you are using the binary scanner capabilities, be aware that we only have a limited number of binary checkers (see table above) so we can only detect those libraries. Contributions of new checkers are always welcome! You can also use an alternate way to detect components (for example, a bill of materials tool such as tern) and then use the resulting list as input to cve-bin-tool to get a more comprehensive vulnerability list.

The tool uses a vulnerability database in order to detect the present vulnerabilities, in case the database is not frequently updated (specially if the tool is used in offline mode), the tool would be unable to detect any newly discovered vulnerabilities. Hence it is highly advised to keep the database updated.

The tool does not guarantee that all vulnerabilities are reported as the tool only has access to a limited number of publicly available vulnerability databases. Contributions to introduce new sources of data to the tool are always welcome.

Whilst some validation checks are performed on the data within the vulnerability database, the tool is unable to assert the quality of the data or correct any discrepancies if the data is incomplete or inconsistent. This may result, for example, in some vulnerability reports where the severity is reported as UNKNOWN.

Feedback & Contributions

Bugs and feature requests can be made via GitHub issues. Be aware that these issues are not private, so take care when providing output to make sure you are not disclosing security issues in other products.

Pull requests are also welcome via git.

  • New contributors should read the contributor guide to get started.

  • Folk who already have experience contributing to open source projects may not need the full guide but should still use the pull request checklist to make things easy for everyone.

CVE Binary Tool contributors are asked to adhere to the Python Community Code of Conduct. Please contact Terri if you have concerns or questions relating to this code of conduct.

Security Issues

Security issues with the tool itself can be reported to Intel’s security incident response team via https://intel.com/security.

If in the course of using this tool you discover a security issue with someone else’s code, please disclose responsibly to the appropriate party.

Full option list

Usage: cve-bin-tool <directory/file to scan>

options:
  -h, --help            show this help message and exit
  -e EXCLUDE, --exclude EXCLUDE
                        Comma separated Exclude directory path
  -V, --version         show program's version number and exit
  --disable-version-check
                        skips checking for a new version
  --disable-validation-check
                        skips checking xml files against schema
  --offline             operate in offline mode
  --detailed            add CVE description in csv or json report (no effect on console, html or pdf)

CVE Data Download:
  Arguments related to data sources and Cache Configuration

  -n {api,api2,json,json-mirror,json-nvd}, --nvd {api,api2,json,json-mirror,json-nvd}
                        choose method for getting CVE lists from NVD
  -u {now,daily,never,latest}, --update {now,daily,never,latest}
                        update schedule for data sources and exploits database (default: daily)
  --nvd-api-key NVD_API_KEY
                        specify NVD API key (used to improve NVD rate limit)
  -d DISABLE_DATA_SOURCE, --disable-data-source DISABLE_DATA_SOURCE
                        comma-separated list of data sources (CURL, EPSS, GAD, NVD, OSV, REDHAT, RSD) to disable (default: NONE) 

  --use-mirror USE_MIRROR
                        use an mirror to update the database

Input:
  directory             directory to scan
  -i INPUT_FILE, --input-file INPUT_FILE
                        provide input filename
  --triage-input-file TRIAGE_INPUT_FILE
                        provide input filename for triage data
  -C CONFIG, --config CONFIG
                        provide config file
  -L PACKAGE_LIST, --package-list PACKAGE_LIST
                        provide package list
  --sbom {spdx,cyclonedx,swid}
                        specify type of software bill of materials (sbom) (default: spdx)
  --sbom-file SBOM_FILE
                        provide sbom filename

Output:
  -q, --quiet           suppress output
  -l {debug,info,warning,error,critical}, --log {debug,info,warning,error,critical}
                        log level (default: info)
  -o OUTPUT_FILE, --output-file OUTPUT_FILE
                        provide output filename (default: output to stdout)
  --html-theme HTML_THEME
                        provide custom theme directory for HTML Report
  -f {csv,json,console,html,pdf}, --format {csv,json,console,html,pdf}
                        update output format (default: console)
                        specify multiple output formats by using comma (',') as a separator
                        note: don't use spaces between comma (',') and the output formats.
  --generate-config {yaml,toml,yaml,toml,toml,yaml}
                        generate config file for cve bin tool in toml and yaml formats.
  -c CVSS, --cvss CVSS  minimum CVSS score (as integer in range 0 to 10) to report (default: 0)
  -S {low,medium,high,critical}, --severity {low,medium,high,critical}
                        minimum CVE severity to report (default: low)
  --metrics             
                        check for metrics (e.g., EPSS) from found cves
  --epss-percentile EPSS_PERCENTILE
                        minimum epss percentile of CVE range between 0 to 100 to report
  --epss-probability EPSS_PROBABILITY
                        minimum epss probability of CVE range between 0 to 100 to report
  --no-0-cve-report     only produce report when CVEs are found
  -A [-], --available-fix [-]
                        Lists available fixes of the package from Linux distribution
  -b [-], --backport-fix [-]
                        Lists backported fixes if available from Linux distribution
  --affected-versions   Lists versions of product affected by a given CVE (to facilitate upgrades)
  --vex VEX             Provide vulnerability exchange (vex) filename
  --sbom-output SBOM_OUTPUT
                        provide software bill of materials (sbom) filename to generate
  --sbom-type {spdx,cyclonedx}
                        specify type of software bill of materials (sbom) to generate (default: spdx)
  --sbom-format {tag,json,yaml}
                        specify format of software bill of materials (sbom) to generate (default: tag)

Merge Report:
  Arguments related to Intermediate and Merged Reports

  -a [APPEND], --append [APPEND]
                        save output as intermediate report in json format
  -t TAG, --tag TAG     add a unique tag to differentiate between multiple intermediate reports
  -m MERGE, --merge MERGE
                        comma separated intermediate reports path for merging
  -F FILTER, --filter FILTER
                        comma separated tag string for filtering intermediate reports

Checkers:
  -s SKIPS, --skips SKIPS
                        comma-separated list of checkers to disable
  -r RUNS, --runs RUNS  comma-separated list of checkers to enable

Database Management:
  --import-json IMPORT_JSON
                        import database from json files chopped by years
  --ignore-sig          do not verify PGP signature while importing json data
  --log-signature-error
                        when the signature doesn't match log the error only instead of halting (UNSAFE)
  --verify PGP_PUBKEY_PATH
                        verify PGP sign while importing json files
  --export-json EXPORT_JSON
                        export database as json files chopped by years
  --pgp-sign PGP_PRIVATE_KEY_PATH
                        sign exported json files with PGP
  --passphrase PASSPHRASE
                        required passphrase for signing with PGP
  --export EXPORT       export database filename
  --import IMPORT       import database filename

Exploits:
  --exploits            check for exploits from found cves

Deprecated:
  -x, --extract         autoextract compressed files
  --report              Produces a report even if there are no CVE for the respective output format

For further information about all of these options, please see the CVE Binary Tool user manual.

CVE Binary Tool User Manual

The CVE Binary Tool scans for a number of common, vulnerable open source components like openssl, libpng, libxml2, expat etc. to let you know if a given directory or binary file includes common libraries with known vulnerabilities., known as CVEs(Common Vulnerabilities and Exposures).

Usage: cve-bin-tool

You can also do python -m cve_bin_tool.cli which is useful if you’re trying the latest code from the cve-bin-tool github.

optional arguments:
  -h, --help            show this help message and exit
  -e EXCLUDE, --exclude EXCLUDE
                        Comma separated Exclude directory path
  -V, --version         show program's version number and exit
  --disable-version-check
                        skips checking for a new version
  --disable-validation-check
                        skips checking xml files against schema
  --offline             operate in offline mode
  --detailed            display detailed report

CVE Data Download:
  Arguments related to data sources and Cache Configuration

  -n {api,api2,json-nvd,json-mirror}, --nvd {api,api2,json-nvd,json-mirror}
                        choose method for getting CVE lists from NVD
  -u {now,daily,never,latest}, --update {now,daily,never,latest}
                        update schedule for data sources and exploits database (default: daily)
  --nvd-api-key NVD_API_KEY
                        specify NVD API key (used to improve NVD rate limit)
  -d {NVD,OSV,GAD,REDHAT,CURL} [{NVD,OSV,GAD,REDHAT,CURL} ...], --disable-data-source {NVD,OSV,GAD,REDHAT,CURL} [{NVD,OSV,GAD,REDHAT,CURL} ...]
                        specify data sources that should be disabled

Input:
  directory             directory to scan
  -i INPUT_FILE, --input-file INPUT_FILE
                        provide input filename
  -C CONFIG, --config CONFIG
                        provide config file
  -L PACKAGE_LIST, --package-list PACKAGE_LIST
                        provide package list
  --sbom {spdx,cyclonedx,swid}
                        specify type of software bill of materials (sbom) (default: spdx)
  --sbom-file SBOM_FILE
                        provide sbom filename

Output:
  -q, --quiet           suppress output
  -l {debug,info,warning,error,critical}, --log {debug,info,warning,error,critical}
                        log level (default: info)
  -o OUTPUT_FILE, --output-file OUTPUT_FILE
                        provide output filename (default: output to stdout)
  --html-theme HTML_THEME
                        provide custom theme directory for HTML Report
  -f {csv,json,console,html,pdf}, --format {csv,json,console,html,pdf}
                        update output format (default: console)
                        specify multiple output formats by using comma (',') as a separator
                        note: don't use spaces between comma (',') and the output formats.
  -c CVSS, --cvss CVSS  minimum CVSS score (as integer in range 0 to 10) to report (default: 0)
  --epss-percentile     minimum EPSS percentile of CVE range between 0 to 100 to report 
                        (input value can also be floating point)(default: 0)
  --epss-probability     minimum EPSS probability of CVE range between 0 to 100 to report 
                        (input value can also be floating point)(default: 0)
  -S {low,medium,high,critical}, --severity {low,medium,high,critical}
                        minimum CVE severity to report (default: low)
  --no-0-cve-report     only produce report when CVEs are found
  -A [<distro_name>-<distro_version_name>], --available-fix [<distro_name>-<distro_version_name>]
                        Lists available fixes of the package from Linux distribution
  -b [<distro_name>-<distro_version_name>], --backport-fix [<distro_name>-<distro_version_name>]
                        Lists backported fixes if available from Linux distribution
  --affected-versions   Lists versions of product affected by a given CVE (to facilitate upgrades)
  --vex VEX             Provide vulnerability exchange (vex) filename
  --sbom-output SBOM_OUTPUT
                        provide software bill of materials (sbom) filename to generate
  --sbom-type {spdx,cyclonedx}
                        specify type of software bill of materials (sbom) to generate (default: spdx)
  --sbom-format {tag,json,yaml}
                        specify format of software bill of materials (sbom) to generate (default: tag)

Merge Report:
  Arguments related to Intermediate and Merged Reports

  -a [APPEND], --append [APPEND]
                        save output as intermediate report in json format
  -t TAG, --tag TAG     add a unique tag to differentiate between multiple intermediate reports
  -m MERGE, --merge MERGE
                        comma separated intermediate reports path for merging
  -F FILTER, --filter FILTER
                        comma separated tag string for filtering intermediate reports

Checkers:
  -s SKIPS, --skips SKIPS
                        comma-separated list of checkers to disable
  -r RUNS, --runs RUNS  comma-separated list of checkers to enable

Database Management:
  --export EXPORT       export database filename
  --import IMPORT       import database filename

Exploits:
  --exploits            check for exploits from found cves

Deprecated:
  -x, --extract         autoextract compressed files
  CVE Binary Tool autoextracts all compressed files by default now
  --report              Produces a report even if there are no CVE for the respective output format
  CVE Binary Tool produces report by default even if there are no CVEs

Available checkers

accountsservice

acpid

apache_http_server

apcupsd

apparmor

asn1c

assimp

asterisk

atftp

avahi

axel

bash

bind

binutils

bird

bison

bluez

boinc

botan

bro

bubblewrap

busybox

bwm_ng

bzip2

c_ares

capnproto

ceph

chess

chrony

civetweb

clamav

collectd

commons_compress

connman

coreutils

cpio

cronie

cryptsetup

cups

curl

cvs

darkhttpd

dav1d

davfs2

dbus

debianutils

dhclient

dhcpcd

dhcpd

dmidecode

dnsmasq

docker

domoticz

dosfstools

dotnet

dovecot

doxygen

dpkg

dropbear

e2fsprogs

ed

elfutils

emacs

enscript

exfatprogs

exim

exiv2

f2fs_tools

faad2

fastd

ffmpeg

file

firefox

flac

fluidsynth

freeradius

freerdp

fribidi

frr

gawk

gcc

gdal

gdb

gdk_pixbuf

gimp

git

glib

glibc

gmp

gnomeshell

gnupg

gnutls

go

gpgme

gpsd

graphicsmagick

grep

grub2

gstreamer

gupnp

gvfs

gzip

haproxy

harfbuzz

haserl

hdf5

heimdal

hostapd

hunspell

hwloc

i2pd

icecast

icu

iperf3

ipmitool

ipsec_tools

iptables

irssi

iucode_tool

iwd

jack2

jacksondatabind

janus

jhead

jq

json_c

kbd

keepalived

kerberos

kexectools

kodi

kubernetes

ldns

lftp

libarchive

libass

libbpg

libcoap

libconfuse

libcurl

libdb

libde265

libebml

libevent

libexpat

libgcrypt

libgd

libgit2

libheif

libical

libidn2

libinput

libjpeg

libjpeg_turbo

libksba

liblas

libmatroska

libmemcached

libmicrohttpd

libmodbus

libnss

libpcap

libraw

librsvg

librsync

libsamplerate

libseccomp

libsndfile

libsolv

libsoup

libsrtp

libssh

libssh2

libtasn1

libtiff

libtomcrypt

libupnp

libuv

libvips

libvirt

libvncserver

libvorbis

libvpx

libxslt

lighttpd

linux_kernel

lldpd

logrotate

lrzip

lua

luajit

lxc

lynx

lz4

mailx

mariadb

mbedtls

mdadm

memcached

micropython

minetest

mini_httpd

minicom

minidlna

miniupnpc

miniupnpd

moby

modsecurity

monit

mosquitto

motion

mpg123

mpv

msmtp

mtr

mupdf

mutt

mysql

nano

nasm

nbd

ncurses

neon

nessus

netatalk

netdata

netkit_ftp

netpbm

nettle

nghttp2

nginx

ngircd

nmap

node

ntfs_3g

ntp

ntpsec

open_iscsi

open_vm_tools

openafs

opencv

openjpeg

openldap

opensc

openssh

openssl

openswan

openvpn

p7zip

pango

patch

pcre

pcre2

pcsc_lite

perl

php

picocom

pigz

pixman

png

polarssl_fedora

poppler

postgresql

ppp

privoxy

procps_ng

proftpd

protobuf_c

pspp

pure_ftpd

putty

python

qemu

qpdf

qt

quagga

radare2

radvd

raptor

rauc

rdesktop

readline

rpm

rsync

rsyslog

rtl_433

rtmpdump

runc

rust

samba

sane_backends

sdl

seahorse

shadowsocks_libev

snapd

sngrep

snort

socat

sofia_sip

speex

spice

sqlite

squashfs

squid

sslh

stellarium

strongswan

stunnel

subversion

sudo

suricata

sylpheed

syslogng

sysstat

systemd

tar

tcpdump

tcpreplay

terminology

tesseract

thrift

thttpd

thunderbird

timescaledb

tinyproxy

tor

tpm2_tss

traceroute

transmission

trousers

ttyd

twonky_server

u_boot

udisks

unbound

unixodbc

upx

util_linux

varnish

vim

vlc

vorbis_tools

vsftpd

webkitgtk

wget

wireshark

wolfssl

wpa_supplicant

xerces

xml2

xscreensaver

xwayland

yasm

zabbix

zchunk

zeek

zlib

znc

zsh

zstandard

For a quick overview of usage and how it works, you can also see the readme file.

How it works

This scanner looks at the strings found in binary files to see if they match vulnerable versions of a small set of popular open source libraries.

It only matches strings that are of length 3+; this allows the tool to handle versions where the version number is x.y.

It does not attempt to exploit issues or examine code in greater detail. As such, it cannot tell if someone has backported fixes to an otherwise vulnerable version, it merely provides a mapping between strings, versions, and known CVEs.

A list of currently available checkers can be found in the checkers directory or using cve-bin-tool --help command, as can the instructions on how to add a new checker. Support for new checkers can be requested via GitHub issues. (Please note, you will need to be logged in to add a new issue.)

This tool gives a list of CVE numbers. For those not familiar with the process, these can be looked up using a number of different tools, such as the vulnerability search on the CVE Details website. Each CVE field contains a short summary of the issue, a set of severity scores that are combined to make a CVSS score, a list of products known to be affected, and links to more information (which may include links to sample exploits as well as patches to fix the issue).

Installing

cve-bin-tool can be installed via pip. If your PATH environment variable is properly configured, installation will result in cve-bin-tool being accessible globally. If not you can treat cve-bin-tool as python -m cve_bin_tool.cli.

pip install -U cve-bin-tool

If you want the latest and greatest between releases you can grab from GitHub.

pip install -U git+https://github.com/intel/cve-bin-tool

CVE Binary Tool relies on a few command line utilities which are usually present on GNU/Linux systems but you may need to install.

  • file

  • strings

  • tar

  • unzip

  • rpm2cpio

  • cpio

  • ar

  • cabextract

On Windows, it requires

  • ar

  • 7z

  • Expand

Windows has ar and Expand installed in default, but 7z in particular might need to be installed. If you wan to run our test-suite or scan a zstd compressed file, We recommend installing this 7-zip-zstd fork of 7zip. We are currently using 7z for extracting jar, apk, msi, exe and rpm files.

Note: The CVE Binary Tool cannot scan password-protected ZIP files. If you attempt to scan such a file, an error message will be logged regarding the failure in extraction..

Deployment best practices

CVE binary tool is intended for use by developers wishing to track known vulnerabilities against their own code and their dependencies. We expect many users to use continuous integration systems such as Github Actions, and we have our own cve-bin-tool GitHub Action available to make that easy. You can also run it within your existing build/test environments.

We usually assume that the people providing the binaries for scanning will be the same people who set up and control the environment in which they are run. For example, a normal use case would be an open source project scanning their own generated files as a build check. We don’t really expect people to use this as a forensics tool on a compromised system. (Although if you use it that way, we’d love to hear how that worked for you!)

Use user-level permissions with appropriate file system access

You should give cve-bin-tool minimal, user-level permissions. The user for cve-bin-tool will need access to the following things:

  • Read/write access to a cache directory for storing and reading the vulnerability data (~/.cache/cve-bin-tool/).

    • Write access is only needed during data updates, which typically run once a day and can be scheduled separately.

  • Read access to the file/directory to be scanned.

  • Write access to the system temp directory if extracting files.

  • Write access to a directory/file for reports, if you want the report in a file and not just printed to the console.

You should not run cve-bin-tool as root, not even in a sandbox, container, or virtual machine. While “don’t run as root” is pretty standard security advice, we specifically do not want to give cve-bin-tool permission to over-write the system binaries it uses for scanning or extracting files such as strings or rpm2cpio, as those could be used to greatly increase the risk/severity of any issue found in cve-bin-tool or its dependencies.

For similar reasons, making sure that cve-bin-tool doesn’t have access to things like publicly-facing webserver files directories is also a good idea. Many users prefer to keep vulnerability reports private anyhow, but this is a case where choosing radical transparency could also become part of an attack chain.

Use restrictions on system temp files

CVE-bin-tool will extract a number of different archives into the system temp directory (using the built-in python tempfile library) so that it can then examine strings for signature matching. Although cve-bin-tool parses strings from binaries and doesn’t execute code, you may wish to check that your system temp directory has appropriate permissions and behaviours set to limit risk of another process using the extracted file. As well as basic file permissions, some systems may use namespaces and other tools to further restrict temporary files.

Schedule data updates separately when running parallel scans

By default cve-bin-tool will check the data sources and update if they are older than 24 hours. This is fine for a single process but can cause unnecessary churn if multiple processes are being run at the same time.

You can read more information in the how-to guide Best practices for running multiple scans at once.

The update job can be further constrained to have only access to the database cache directory, if you so choose.

Using cve-bin-tool within a throwaway environment

CVE-bin-tool is intended for use as part of continuous integration testing, and many such systems use throwaway containers or virtual machines to mitigate risk. If you’re intending to do this, you will probably want to find a way to store and re-use the vulnerability data, probably by copying it into the “fresh” environment.

In Github Actions, you can use actions/cache to do this. You can see how we handle caching in our GitHub Actions cache job. If you’re not using Github Actions, you may find it useful to look at the instructions for using cve-bin-tool offline as they show the process for separating the download of data and the scan.

Don’t scan arbitrary binary files without additional sandboxing

Periodically, someone suggests creating a service which runs cve-bin-tool and allows users to upload random binaries to the system for analysis. We don’t really recommend this, as getting random binaries from the internet never ends well. But if you were going to do it, be aware that you’d likely need additional protections similar to any other setup for testing unknown-and-potentially-malicious binaries. You may want to look at what others have written on how to build a malware analysis lab if you’re not sure what sort of protections are needed.

In general, we want people to control their own services for scanning their own binaries. So rather than running a cve-bin-tool web service for the whole world, we encourage individuals to use the cve-bin-tool GitHub Action or run it as a check in your existing build/test environment.

Fixing Known Issues / What should I do if it finds something?

The most recommended way to fix a given CVE is to upgrade the package to a non-vulnerable version. Ideally, a CVE is only made public after a fix is available, although this is not always the case.

If this is not possible for some reason, search for the CVE number to get information on possible workarounds and patches that could be backported to other versions. Note that neither workarounds nor backported fixes can be detected by this tool, so your binary will continue to show up as vulnerable even though it may now be safely mitigated and result in a false positive. To avoid this problem, we recommend classifying CVE as Mitigated as explained in the Input section.

Data Sources

The following data sources are used to get CVE data to find CVEs for a package:

National Vulnerability Database (NVD)

This data source consists of majority of the CVE entries and is essential to provide vendor data for other data sources such as OSV, therefore disabling the download of CVE data from this source is not possible, --disable-data-source "NVD" only disables CVEs from displaying in output.

The National Vulnerability Database (NVD) has changed its access policy and it is now recommended that users obtain an NVD API Key to ensure access to the full database. The cve-bin-tool supports using an NVD API KEY for retrieving vulnerability data from the NVD.

NVD requires users to create and use an NVD_API_KEY to use their API. To set up an API_KEY ,please visit Request an API Key .

There are three ways to set up the NVD API Key in cve-bin-tool:

  • By using environment variable

  • By defining it in config file

  • By stating it in command line interface(cli)

By using environment variable

  • Open a terminal window and navigate to the directory where you have installed cve-bin-tool.

  • Enter the following command to set your NVD API key as an environment variable:

  export NVD_API_KEY=<your api key>
  • Replace <your api key> with your actual NVD API key.

  • You can verify that the environment variable has been set by entering the following command:

echo $NVD_API_KEY
  • Now, when you run cve-bin-tool, it will automatically use the NVD API key that you have set as an environment variable.

    Note : The steps to set environment variables may vary depending on the operating system you are using. The above steps are for Unix-based systems such as Linux and macOS. On Windows, you can set environment variables using the System Properties dialog or the Command Prompt.

By defining it in config file

  • Open the cve-bin-tool configuration file (config.yaml or config.toml)

  • Under the [nvd section, add the following line:

  api_key = your_api_key_here
  • Replace your_api_key_here with your NVD API Key.

  • Save the changes to the configuration file.

  • which can be passed to the cve-bin-tool

 cve-bin-tool --config config.toml

By stating it in command line interface(cli)

  • To set the flag --nvd-api-key to the API Key you have been provided.

  • You can implement that in the following way :

cve-bin-tool --nvd-api-key your_api_key_here

Once you have set up your NVD API Key, cve-bin-tool will use it to retrieve vulnerability data from the NVD. This will ensure that you have access to the full database and will reduce the likelihood of encountering errors due to limited access.

If for any reason, the NVD API Key is not working, cve-bin-tool will automatically switch to the JSON fallback. However, it is highly recommended that you verify that your API Key is working properly to ensure access with the NVD database. To use the json method, use the flag -n json-nvd or --nvd json-nvd . You can use it in the following way

cve-bin-tool --nvd-api-key your_api_key_here -n json-nvd

Note : If you have problems downloading the initial data , it may be due to the NVD’s current rate limiting scheme which block users entirely if they aren’t using an API key.

If you don’t want to use the NVD API, you can also download their json files without setting up a key. Please note that this method is slower for getting updates but is more ideal if you just want to try out the cve-bin-tool for the first time.

If the API key is not used, the time to access and download the data from the NVD database will be significantly increased due to the rate limiting algorithm implemented by the NVD. This algorithm limits the number of requests that can be made to the NVD database per unit time, and if this limit is exceeded, the user will be blocked from accessing the data for a period of time.

So without an API key, users may experience slower download speeds and longer wait times for their requests to be processed, as they will be subject to these rate limits. Therefore, it is highly recommended to obtain and use an NVD API key for optimal performance and functionality when working with the cve-bin-tool.

Open Source Vulnerability Database (OSV)

This data source is based on the OSV schema from Google, and consists of CVEs from different ecosystems that might not be covered by NVD. NVD is given priority if there are duplicate CVEs as some CVEs from OSV may not contain CVSS scores. Using OSV will increase number of CVEs and time taken to update the database but searching database for vulnerabilities will have similar performance.

Gitlab Advisory Database (GAD)

This data source consists of security advisories used by the GitLab dependency scanner. The number of CVEs added from this data source is similar to OSV.

RedHat Security Database (REDHAT)

This data source contains CVEs pertaining to RedHat Products.

Access to the data is subject to Legal Notice.

Curl Database (Curl)

This data source provides the CVEs for the CURL product.

Limitations

The last release of this tool to support python 2.7 is 0.3.1. Please use python 3.8+ for development and future versions. Linux and Windows are supported, as is usage within cygwin on windows.

This tool does not scan for all possible known public vulnerabilities, it only scans for specific commonly vulnerable open source components. A complete list of currently supported library checkers can be found in the checkers directory.

As the name implies, this tool is intended for use with binaries. If you have access to a known list of product names and versions, we do have an option --input-file that can be used to look up known vulnerabilities given a CSV or JSON file or using the --sbom-file option to scan a Software Bill of Materials (SBOM) file. Scanning of product names within an SBOM file is case insensitive.

See the detailed description of --input-file for more details.

The tool does not guarantee that all vulnerabilities are reported as the tool only has access to a limited number of publicly available vulnerability databases. Whilst some validation checks are performed on the data within the vulnerability database, the tool is unable to assert the quality of the data or correct any discrepancies if the data is incomplete or inconsistent. This may result, for example, in some vulnerability reports where the severity is reported as UNKNOWN.

Architecture

The CVE binary tool is utilized to identify vulnerabilities within a software. When the CVE binary tool is initiated, it commences by populating CVE database which include downloading, and updating the database from various sources. Currently, the CVE binary tool employs diverse sources for downloading CVEs and their associated information, including curl, EPSS, GAD, NVD, OSV, and RedHat.

Once the database is populated, the CVE binary tool conducts searches for CVEs using two distinct methods:

  • The first approach involves examining language component lists (e.g., requirement.txt, package.json) for different programming languages. Presently, the CVE binary tool provides support for 11 languages: Dart, Go, Java, JavaScript, Python, Perl, PHP, R, Ruby, Rust, and Swift. If your desired language is not listed, you can refer to this guide on how to add a parser for it.

  • The second method employs checkers to gather information about software vulnerabilities. Checkers consist of predefined information about software entities. The CVE binary tool scans binaries for patterns matching the descriptions provided by the checkers, thereby extracting details like software version and vendor. At present, the CVE binary tool includes over 300 checkers. Crafting new checkers is a straightforward process and can serve as a beginner-friendly task. You can learn more about adding checkers here.

After collecting information about the software and its version, the CVE binary tool proceeds to search for corresponding vulnerabilities within the CVE database. Following the database query, additional information is sought, such as available fixes and, depending on the scan type, potential exploits for the identified CVEs.

Subsequently, the tool generates an output based on the gathered information. The CVE binary tool supports multiple output formats, including console, CSV, JSON, HTML, and PDF.

Furthermore, the CVE binary tool offers an option to detect vulnerabilities within a provided CSV file.

Database Structure

The CVE Binary Tool database comprises three tables: cve_severity, cve_range, and cve_exploited. The cve_range and cve_severity tables are connected. The cve_range has a foreign key referencing the cve_number and data_source in the cve_severity table. The cve_severity table holds information about the severity of vulnerabilities, with the cve_number serving as the primary key. The cve_range table is linked to cve_severity via the cve_number and data_source columns, establishing a relationship between vulnerability severity and affected product ranges. The cve_exploited table tracks exploited vulnerabilities, utilizing the cve_number as the primary key. This database structure enables effective management and analysis of CVE-related data, facilitating identifying and assessing vulnerabilities and their associated exploit instances.

database structure of CVE Binary Tool

Metric

EPSS

The Exploit Prediction Scoring System (EPSS) is a data-driven tool designed to help estimate the likelihood of a software vulnerability being exploited in the real world. Its purpose is to assist cybersecurity teams in prioritizing which vulnerabilities to address first. While other standards focus on inherent vulnerability traits and severity, they often lack the ability to evaluate the actual threat level.

EPSS bridges this gap by incorporating up-to-date threat information from CVE and real-world exploit data. Using this data, EPSS generates a probability score ranging from 0 to 1 (equivalent to 0% to 100%). A higher score indicates a higher likelihood of a vulnerability being exploited. For more information about EPSS here

Different output showing metrics

  • Console

console table

console metric table

  • HTML

HTML metric table

  • PDF

PDF metric table

  • CSV

CSV metric table

  • JSON

JSON metric table

Optional Arguments

-e EXCLUDE, –exclude EXCLUDE

This option allows one the skip a comma-separated lists of paths. This can be useful for excluding certain files and directories from the scan which will also decrease the scanning time.

-h, –help

This option shows a help message and exits.

-V, –version

This option shows program’s version number and exits.

–disable-version-check

This option skips checking for a new version of the program.

–disable-validation-check

This option skips validating XML files (e.g. within an SBOM) against a schema.

–offline

The offline flag is used to run the CVE Bin Tool in offline mode, where no internet connection is required. This is useful when working in secure or isolated environments where internet access is restricted.

When the offline flag is enabled, the tool will only use the local CVE data that has been previously downloaded and stored on the system. To enable offline mode, simply include the --offline flag when running the tool.

Note: In order to utilize this feature, it is essential to download the database beforehand. If the database is not downloaded, the tool will prompt an error to download the database, and the test will not be able to run.

CVE Data Download Arguments

-u {now,daily,never,latest}, –update {now,daily,never,latest}

This option controls the frequency of updates for the CVE data from the National Vulnerability Database. By default, the tool checks the staleness of the data with every run, and if the data is more than one day old, it gets an update from NVD. You may also choose to update the data now (in which case all cached data is deleted and a full new download is done) or never in which case the staleness check is not done and no update is requested. The now and never modes can be combined to produce alternative update schedules if daily is not the desired one.

-n {json-nvd,json-mirror,api,api2}, –nvd {json-nvd,json-mirror,api,api2}

This option selects how CVE data is downloaded from the National Vulnerability Database. The api option previously used the NVD CVE Retrieval API version 1.0, which is now deprecated. Using --nvd api will automatically switch to the --nvd api2 option. The api2 option uses the later NVD CVE Retrieval API version 2.0. The results from this API are updated as quickly as the NVD database. A major benefit of using this NVD API is incremental updates which basically means you won’t have to download the complete feed again in case you want the latest CVE entries from NVD. See the detailed guide on incremental updates for more details.

You may also choose to update the data using json-nvd option which uses the JSON feeds available on this page. These per-year feeds are updated once per day. This mode was the default for CVE Binary Tool prior to the 3.0 release.

–nvd-api-key NVD_API_KEY

An NVD API key allows registered users to make a greater number of requests to the API. At this time, the NVD API documentation) says, “The public rate limit (without an API key) is 10 requests in a rolling 60 second window; the rate limit with an API key is 100 requests in a rolling 60 second window.”

CVE Binary tool by default queries the NVD database once per day and caches the results to help alleviate load on the NVD servers. Users who update more regularly or who are running the tool in shared environments (such as cloud providers or GitHub Actions) may find themselves hitting the rate limits despite those precautions and should obtain and use an NVD API key with CVE Binary Tool.

To get an API key, users should visit the NVD API key request page.

Note : It is recommended to use this method as NVD’s current rate limiting scheme may block the users entirely if they aren’t using an API key.

There are 2 ways to save the NVD API KEY -

On LINUX -

Set the NVD_API_KEY as an environment variable (on linux: export NVD_API_KEY=your-key-here, this statement can be added to your shell file which contains environment variables (Ex: .bashrc, .zshrc)).

On WINDOWS - a) On the Windows taskbar, right-click the Windows icon and select System.

b) In the Settings window, under Related Settings, click Advanced system settings.

c) On the Advanced tab, click Environment Variables.

d) Click New to create a new environment variable.

e) Set Variable Name: NVD_API_KEY & Value:your-key-here.

Using Tool - You can also specify NVD_API_KEY in the config file using -C switch. Documentation on the config file can be found here: check the yaml and toml config file.

Related: NVD API key announcement

-d {NVD,OSV,GAD,CURL} [{NVD,OSV,GAD,CURL} …], –disable-data-source {NVD,OSV,GAD,CURL} [{NVD,OSV,GAD,CURL} …]

This option disables a data source. CVEs from disabled data sources are not downloaded or reported, with the exception of the NVD data source, where CVEs will still be downloaded but will not be reported if it is disabled. By default, all data sources are enabled. As the data sources supported may change between releases, use cve-bin-tool --help option to find the list of supported data sources for the release.

To disable multiple data sources, the data sources should be specified as a comma-separated list e.g. -d "OSV,GAD".

Checkers Arguments

-s SKIPS, –skips SKIPS

This option allows one to skip (disable) a comma-separated list of checkers. This can be useful for improving the performance of the tool when you have some prior knowledge about what checkers may apply to the binary you are scanning.

-r CHECKERS, –runs CHECKERS

This option allows one to enable a comma-separated list of checkers.

Input Arguments

directory (positional argument)

Specify path to directory you want to scan.

-i INPUT_FILE, –input-file INPUT_FILE

This option extends functionality of csv2cve for other formats like JSON.

You can provide either CSV or JSON file as input_file with vendor, product and version fields. You can also add optional fields like remarks, comments, cve_number, severity. Here’s the detailed description and usecase of each fields:

  1. vendor, product, version - To query locally stored CVE database and give you a list of CVEs that affect each vendor, product, version listed.

  2. remarks - remarks help you categorized different CVEs into different categories like:

    • NewFound (1, n, N)

    • Unexplored (2, u, U)

    • Confirmed (3, c, C)

    • Mitigated, (4, m, M)

    • False Positive (5, f, F)

    • Not Affected (6, i, I)

  • All the characters denoted in parentheses are aliases for that specific value. Output will be displayed in the same order as priority given to the remarks.

  1. comments - You can write any comments you want to write in this field. This will be ignored in the console output but will be propagated as it is in CSV, JSON or HTML formats.

  2. severity - This field allows you to adjust severity score of specific product or CVE. This can be useful in the case where CVE affects a portion of the library that you aren’t using currently but you don’t want to ignore it completely. In that case, you can reduce severity for this CVE.

  3. cve_number - This field give you fine grained control over output of specific CVE. You can change remarks, comments and severity for specific CVE instead of whole product.

Note that --input-file, unlike cve-bin-tool directory scan, will work on any product known in the National Vulnerability Database, not only those that have checkers written.

Note: For backward compatibility, we still support csv2cve command for producing CVEs from csv but we recommend using new --input-file command instead.

–triage-input-file INPUT_FILE

This option allows you to provide triage data and incorporate that into the output so that people could spend less time re-triaging. The supported format is the CycloneDX VEX format which can be generated using the --vex option. For the triage process, the state value in the analysis section of each CVE should have one of the following values:

"under_review" - this is the default state and should be used to indicate the vulnerability is to be reviewed
"in_triage" - this should be used to indicate that the vulnerability is being reviewed
"exploitable" - this should be used to indicate that the vulnerability is known to be exploitable
"not_affected" - this should be used to indicate that the vulnerability has been mitigated

The detail value in the analysis section can be used to provide comments related to the state

For example, if input_file.csv contains the following data:

| vendor          | product   | version   |
| --------------- | --------- | --------- |
| plot            | plotly    | h5.10.0   |
| pocoo           | jinja2    | 3.1.2     |
| aiohttp_project | aiohttp   | 3.8.1     |
| pyyaml          | pyyaml    | 6.0       |
| python          | requests  | 2.28.1    |
| python          | urllib3   | 1.26.12   |
| skontar         | cvss      | 2.5       |
| getbootstrap    | bootstrap | 5.2.0     |
| plotly          | plotly.js | 2.13.2    |

Where aiohttp_project and plotly are affected by CVE-2022-33124 and GMS-2016-69, respectively, you could provide the following triage file:

{
   "bomFormat": "CycloneDX",
   "specVersion": "1.4",
   "version": 1,
   "vulnerabilities": [
      {
         "id": "GMS-2016-69",
         "source": {
            "name": "NVD",
            "url": "https://nvd.nist.gov/vuln/detail/GMS-2016-69"
         },
         "ratings": [
            {
               "source": {
                  "name": "NVD",
                  "url": "https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?name=GMS-2016-69&vector=unknown&version=2.0"
               },
               "score": "unknown",
               "severity": "unknown",
               "method": "CVSSvunknown",
               "vector": "unknown"
            }
         ],
         "cwes": [],
         "description": "If an attacker can trick an unsuspecting user into viewing a specially crafted plot on a site that uses plotly.js, then the attacker could potentially retrieve authentication tokens and perform actions on behalf of the user.",
         "recommendation": "",
         "advisories": [],
         "created": "NOT_KNOWN",
         "published": "NOT_KNOWN",
         "updated": "NOT_KNOWN",
         "analysis": {
            "state": "not_affected",
            "response": [ "code_not_reachable" ],
            "justification": "",
            "detail": ""
         },
         "affects": [
            {
               "ref": "urn:cdx:NOTKNOWN/1#plotly.js:2.13.2"
            }
         ]
      }
   ]
}

Then when you invoke cve-bin-tool like this:

cve-bin-tool -i="input_file.csv" --triage-input-file triage.vex

The output will look like following:

╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║                                            CVE BINARY TOOL version: 3.1.1                                            ║
╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝

 • Report Generated: 2022-11-09  13:52:20
 • Time of last update of CVE Data: 2022-11-09  13:39:31
╭─────────────╮
│ CVE SUMMARY │
╰─────────────╯
┏━━━━━━━━━━┳━━━━━━━┓
┃ Severity ┃ Count ┃
┡━━━━━━━━━━╇━━━━━━━┩
│ CRITICAL │ 0     │
│ HIGH     │ 0     │
│ MEDIUM   │ 1     │
│ LOW      │ 0     │
└──────────┴───────┘
╭───────────────────╮
│  Unexplored CVEs  │
╰───────────────────╯
┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ Vendor          ┃ Product ┃ Version ┃ CVE Number     ┃ Source ┃ Severity ┃ Score (CVSS Version) ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│ aiohttp_project │ aiohttp │ 3.8.1   │ CVE-2022-33124 │ NVD    │ MEDIUM   │ 5.5 (v3)             │
└─────────────────┴─────────┴─────────┴────────────────┴────────┴──────────┴──────────────────────┘
┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━┳━━━━━━━━━━┓
┃ Vendor          ┃ Product ┃ Version ┃ Root ┃ Filename ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━╇━━━━━━━━━━┩
│ aiohttp_project │ aiohttp │ 3.8.1   │      │          │
└─────────────────┴─────────┴─────────┴──────┴──────────┘
╭──────────────────╮
│  Mitigated CVEs  │
╰──────────────────╯
┏━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ Vendor ┃ Product   ┃ Version ┃ CVE Number  ┃ Source ┃ Severity ┃ Score (CVSS Version) ┃
┡━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│ plotly │ plotly.js │ 2.13.2  │ GMS-2016-69 │ GAD    │ unknown  │ unknown              │
└────────┴───────────┴─────────┴─────────────┴────────┴──────────┴──────────────────────┘
┏━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━┳━━━━━━━━━━┓
┃ Vendor ┃ Product   ┃ Version ┃ Root ┃ Filename ┃
┡━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━╇━━━━━━━━━━┩
│ plotly │ plotly.js │ 2.13.2  │      │          │
└────────┴───────────┴─────────┴──────┴──────────┘

–sbom-file SBOM_FILE

This option runs a CVE scan on the specified Software Bill of Materials (SBOM) file. The tool supports SBOM files in a number of formats including SPDX and CycloneDX. Scanning of product names within an SBOM file is case insensitive. To determine the format of the SBOM file, the following filename conventions are followed

SBOM Format Filename extension
SPDX TagValue .spdx
SPDX RDF .spdx.rdf
SPDX JSON .spdx.json
SPDX YAML .spdx.yaml
SPDX YAML .spdx.yml
SPDX XML .spdx.xml
CycloneDX XML .xml
CycloneDX JSON .json
SWID XML .xml

The type of SBOM is assumed to be SPDX unless specified using the --sbom option.

-L PACKAGE_LIST, –package-list PACKAGE_LIST

This option runs a CVE scan on installed packages listed in a package list. It takes a python package list (requirements.txt) or a package list of packages of systems that has dpkg, pacman or rpm package manager as an input for the scan. This option is much faster and detects more CVEs than the default method of scanning binaries.

An example of the package list for Linux systems:

bash
unzip
firefox
sed
python3

Note: The packages in the package list should be installed in the system before the scan. Run

  • pip install -r requirements.txt to install python packages

  • sudo apt-get install $(cat package-list) for packages in a Debian based system

  • sudo yum install $(cat package-list)for packages in a CentOS/Fedora system

  • sudo pacman -S $(cat package-list) for packages in a system that uses pacman package manager (Arch Linux, Manjaro etc.)

Note: Don’t use invalid package names in the package list, as it may throw errors.

You can test it using our test package list with following command:

cve-bin-tool -L test/txt/test_ubuntu_list.txt

You can get a package list of all installed packages in

  • a system using dpkg package manager by running dpkg-query -W -f '${binary:Package}\n' > pkg-list

  • a system using pacman package manager by running pacman -Qqe > pkg-list

  • a system using rpm package manager by running rpm -qa --queryformat '%{NAME}\n' > pkg-list

in the terminal and provide it as an input by running cve-bin-tool -L pkg-list for a full package scan.

-C CONFIG, –config CONFIG

We currently have number of command line options and we understand that it won’t be feasible to type all the option everytime you want to run a scan. You can use --config option to provide configuration file for the tool. You can still override options specified in config file with command line arguments. We support 2 most popular config file format:

  1. TOML which is popular amongst Python developer and very similar to INI file. If you are not familiar with TOML checkout official TOML documentation

  2. YAML which is popular amongst devops community and since many of our users are devops. We also support YAML as config file format. You can find out more about YAML at yaml.org

You can see our sample TOML config file here and sample YAML config file here.

You have to specify either a directory to scan and/or an input file containing vendor, product and version fields either in JSON or CSV format.

Yaml example file
cve_data_download:
  #set your nvd api key
  nvd_api_key:your-key-here

input:
  # Directory to scan
  directory: test/assets
  # To supplement triage data of previous scan or run standalone as csv2cve
  # Currently we only support vex file.
  triage_input_file: triage.vex

checker:
  # list of checkers you want to skip
  skips:
    - python
    - bzip2
  # list of checkers you want to run
  runs:
    - curl
    - binutils

output:
  # specify output verbosity from [debug, info, warning, error, critical]
  # verbosity will decreases as you go left to right (default: info)
  log_level: debug
  # if true then we don't display any output and
  # only exit-code with number of cves get returned
  # overwrites setting specified in log_level
  # Note: it's lowercase true or false
  quiet: false
  # specify one of an output format: [csv, json, html, console] (default: console)
  format: console
  # provide output filename (optional)
  # if not specified we will generate one according to output format specified
  output_file: ''
  # specify minimum CVE severity level to report from [low, medium, high, critical] (default: low)
  severity: low
  # specify minimum CVSS score to report from integer range 0 to 10 (default: 0)
  cvss: 0
other:
  # set true if you want to skip checking for newer version
  disable_version_check: false
  # update schedule for NVD database (default: daily)
  update: daily
  # set true if you want to autoextract archive files. (default: true)
  extract: true
Toml example file
[cve_data_download]

#set your nvd api key
nvd_api_key = "your-key-here"

[input]

# Directory to scan
directory = "test/assets"

# To supplement triage data of previous scan or run standalone as csv2cve
# Currently we only support csv and json file.
input_file = "test/csv/triage.csv"

[checker]

# list of checkers you want to skip
skips = ["python", "bzip2"]

# list of checkers you want to run
runs = ["curl", "binutils"]

[output]

# specify output verbosity from ["debug", "info", "warning", "error", "critical"]
# verbosity will decreases as you go left to right (default: "info")
log_level = "debug"

# if true then we don't display any output and
# only exit-code with number of cves get returned
# overwrites setting specified in log_level
# Note: it's lowercase true or false
quiet = false

# specify one of an output format: ["csv", "json", "html", "console"] (default: "console")
format = "console"

# provide output filename (optional)
# if not specified we will generate one according to output format specified
output_file = ""

# specify minimum CVE severity level to report from ["low", "medium", "high", "critical"] (default: "low")
severity = "low"

# specify minimum CVSS score to report from integer range 0 to 10 (default: 0)
cvss = 0

[other]
# set true if you want to skip checking for newer version
disable_version_check = false

# update schedule for NVD database (default: daily)
update = "daily"

# set true if you want to autoextract archive files. (default: true)
extract = true

Output Arguments

Although the examples in this section show results for a single library to make them shorter and easier to read, the tool was designed to be run on entire directories and will scan all files in a directory if one is supplied.

-o OUTPUT_FILE, –output-file OUTPUT_FILE

This option allows you to specify the filename for the report, rather than having CVE Binary Tool generate it by itself.

–html-theme HTML_THEME

This option specifies the theme directory to be used in formatting the HTML report.

-f {csv,json,console,html}, –format {csv,json,console,html}

This option allows the CVE Binary Tool to produce a report in an alternate format. This is useful if you have other tools which only take a specific format. The default is console which prints category wise beautiful tables of CVEs on terminal.

  1. --format csv - write output file in csv (comma separated) format.

vendor,product,version,cve_number,severity,remarks,comments
haxx,curl,7.34.0,CVE-2014-0015,MEDIUM,Mitigated,
haxx,curl,7.34.0,CVE-2014-0138,MEDIUM,NewFound,
haxx,curl,7.34.0,CVE-2014-0139,MEDIUM,Unexplored,
  1. --format json - write output file in json (javascript object notation) format.

[
  {
    "vendor": "haxx",
    "product": "curl",
    "version": "7.34.0",
    "cve_number": "CVE-2014-0015",
    "severity": "MEDIUM",
    "remarks": "Mitigated",
    "comments": ""
  },
  {
    "vendor": "haxx",
    "product": "curl",
    "version": "7.34.0",
    "cve_number": "CVE-2014-0138",
    "severity": "MEDIUM",
    "remarks": "NewFound",
    "comments": ""
  }
]
  1. --format console - prints in nice colored tabular format.


    cve-bin-tool: Report Generated: 2020-07-31  17:49:56
    1. NewFound CVEs:
    Vendor, Product, Version, CVE Number   , Severity
    haxx  , curl   , 7.34.0 , CVE-2014-0138, HIGH
    haxx  , curl   , 7.34.0 , CVE-2014-0139, CRITICAL
    haxx  , curl   , 7.34.0 , CVE-2014-0015, MEDIUM
formated console output
  1. --format html - creates a report in html format according to the specified HTML theme.

image

The unexplored and new CVEs will be highlighted, it will look something like this:

image

You can also filter scanned products by remark:

image

  1. --format pdf - creates a report in PDF format.

If you wish to use PDF support, you will need to install the reportlab library separately.

If you intend to use PDF support when you install cve-bin-tool you can specify it and report lab will be installed as part of the cve-bin-tool install:

pip install cve-bin-tool[PDF]

If you’ve already installed cve-bin-tool you can add reportlab after the fact using pip:

pip install --upgrade reportlab

Note that reportlab was taken out of the default cve-bin-tool install because it has a known CVE associated with it (CVE-2020-28463). The cve-bin-tool code uses the recommended mitigations to limit which resources added to PDFs, as well as additional input validation. This is a bit of a strange CVE because it describes core functionality of PDFs: external items, such as images, can be embedded in them, and thus anyone viewing a PDF could load an external image (similar to how viewing a web page can trigger external loads). There’s no inherent “fix” for that, only mitigations where users of the library must ensure only expected items are added to PDFs at the time of generation.

Since users may not want to have software installed with an open, unfixable CVE associated with it, we’ve opted to make PDF support only available to users who have installed the library themselves. Once the library is installed, the PDF report option will function.

You can also specify multiple output formats by using comma (‘,’) as separator:

cve-bin-tool file -f csv,json,html -o report

Note: Please don’t use spaces between comma (‘,’) and the output formats.

-c CVSS, –cvss CVSS

This option specifies the minimum CVSS score (as integer in range 0 to 10) of the CVE to report. The default value is 0 which results in all CVEs being reported.

–epss-percentile

This option specifies the minimum EPSS percentile of CVE range between 0 to 100 to report. The default value is 0 which results in all CVEs being reported.

–epss-probability

This option specifies the minimum EPSS probability of CVE range between o to 100 to report. The default value is 0 which result in all CVEs being reported.

Automatic Metrics Activation

If either --epss-percentile or --epss-probability is set, the system will automatically enable the --metrics option so that the epss data will be loaded and displayed.

-S {low,medium,high,critical}, –severity {low,medium,high,critical}

This option specifies the minimum CVE severity to report. The default value is low which results in all CVEs being reported.

Note that this option is overridden by --cvss parameter if this is also specified.

-A [<distro_name>-<distro_version_name>], –available-fix [<distro_name>-<distro_version_name>]

This option lists the available fixes of the package from Linux distribution if there are any.

The currently supported Linux distributions are:

debian-bullseye
debian-stretch
debian-buster
ubuntu-hirsute
ubuntu-groovy
ubuntu-focal
ubuntu-eoan
ubuntu-disco
ubuntu-cosmic
ubuntu-bionic
ubuntu-artful
ubuntu-zesty
ubuntu-yakkety
ubuntu-xenial

-b [<distro_name>-<distro_version_name>], –backport-fix [<distro_name>-<distro_version_name>]

This option outputs the available backported fixes for the packages with CVEs if there are any.

By default CVE Binary tool checks for backported fixes according to the Linux distribution of the local machine. You can specify the distribution information explicitly in <distro_name>-<distro_version_name> fashion.

cve-bin-tool <path-to-binary> --backport-fix ubuntu-focal

Currently supported options

debian-bullseye
debian-stretch
debian-buster
ubuntu-hirsute
ubuntu-groovy
ubuntu-focal
ubuntu-eoan
ubuntu-disco
ubuntu-cosmic
ubuntu-bionic
ubuntu-artful
ubuntu-zesty
ubuntu-yakkety
ubuntu-xenial

–affected-versions

This options reports the versions of a product affected by a given CVE.

–vex VEX_FILE

This option allows you to specify the filename for a Vulnerability Exchange (VEX) file which contains all the reported vulnerabilities detected by the scan. This file is typically updated (outside of the CVE Binary tool) to record the results of a triage activity and can be used as a file with --input-file parameter.

–sbom-output SBOM_OUTPUT

This option allows you to specify the filename for a Software Bill of Material (SBOM) file which contains all of the components detected by the scan. The generated file can be used as a subsequent input to the CVE Binary tool with --sbom-file parameter.

It is recommended that the following filename conventions are followed in combination with the --sbom-type and --sbom-format parameters.

SBOM Type SBOM Format Filename extension
SPDX TagValue .spdx
SPDX JSON .spdx.json
SPDX YAML .spdx.yaml
SPDX YAML .spdx.yml
CycloneDX JSON .json

–sbom-type

This option is used in combination with the --sbom-output parameter and allows you to specify the type of Software Bill of Material (SBOM) to be generated. SBOMs can be generated in either SPDX or CycloneDX formats.

If this option is not specified, an SPDX SBOM will be generated.

–sbom-format

This option is used in combination with the --sbom-output and --sbom-type parameters and allows you to specify the format of Software Bill of Material (SBOM) to be generated. TagValue, JSON and YAML formats are supported for SPDX SBOMs; all CycloneDX SBOMS are generated in JSON format.

If this option is not specified, the SBOM will be generated in TagValue format (SPDX) or JSON (CycloneDX) formats.

Output verbosity

As well as the modes above, there are two other output options to decrease or increase the number of messages printed:

  1. Quiet mode (-q) suppresses all output but exits with an error number indicating the number of files with known CVEs. This is intended for continuous integration and headless tests, while the other modes are all more human-friendly.

  2. Log mode (-l log_level) prints logs of the specified log_level and above. The default log level is info. The logs can be suppressed by using quiet mode.

Quiet Mode

As the name implies, quiet mode has no console output, and one must check the return code to see if any issues were found. The return value will be the number of files that have been found to have CVEs

Below is what it returns on bash when one file is found to have CVEs:

terri@sandia:~/Code/cve-bin-tool$ cve-bin-tool -q ~/output_test_quiet/openssl
terri@sandia:~/Code/cve-bin-tool$ echo $?
1

Note that errors are returned as negative numbers. Any positive number indicates that CVEs may be present in the code. A good result here is 0.

Logging modes

The logging modes provide additional fine-grained control for debug information.

Merge Report Arguments

Users may wish to create and combine multiple cve-bin-tool reports to track how vulnerability changes over time, how long it takes to fix issues, or other changes between different reports. We have a number of options related to merging report data.

-a INTERMEDIATE_PATH, –append INTERMEDIATE_PATH

This option allows you to save the output in form of an intermediate report which you can later merge with other reports of the same format.
See the detailed guide on intermediate reports for more details.

Intermediate report format

{
  "metadata": {
    "timestamp": "2021-06-17.00-00-30",
    "tag": "backend",
    "scanned_dir": "/home/path/",
    "products_with_cve": 139,
    "products_without_cve": 2,
    "total_files": 49
  },
  "report": [
    {
      "vendor": "gnu",
      "product": "gcc",
      "version": "9.0.1",
      "cve_number": "CVE-2019-15847",
      "severity": "HIGH",
      "score": "7.5",
      "cvss_version": "3",
      "paths": "/home/path/glib.tar.gz,/home/path/gcc.tar.gz",
      "remarks": "NewFound",
      "comments": ""
    }
  ]
}

-t TAG, –tag TAG

This option allows you to save a tag inside the metadata of intermediate reports. By default the value is empty ""

-m INTERMEDIATE_REPORTS, –merge INTERMEDIATE_REPORTS

This option allows you to merge intermediate reports created using -a or --append. The output from the merged report produces a report on the console. But you can also use it along with -f --format and -o --output-file to produce output in other formats. It takes a list of comma-separated filepaths. Merged report can be used as a security vulnerability summary; as such they contain all encountered CVEs in their latest update (meaning last comment and remark).

-F TAGS, –filter TAGS

This allows you to filter out intermediate reports based on the tag. This can be useful while merging multiple intermediate reports from a single path. See detailed guide on filter intermediate reports for more information.

Database Management

–export EXPORT

This option allows you to make a copy of the database. This is typically required as part of setting up offline operation of the tool. If no database exists, this operation has no effect.

–import IMPORT

This option allows you to import a copy of the database (typically created using the --export option). If the specified file does not exist, this operation has no effect.

Deprecated Arguments

-x, –extract

This option allows the CVE Binary Tool to extract compressed files into a temporary directory so the contents can be scanned. If the quiet flag is not used, the list of extracted files will be printed.

CVE Binary Tool by default auto-extract all compressed files inside the directory path. You can always exclude certain paths by using -e --exclude

–report

This option produces a report for all output formats even if there are 0 CVEs. By default CVE Binary tool doesn’t produce an output when there are 0 CVEs.

CVE Binary Tool produces report by default even if there are no CVEs.

SBOM

An SBOM (Software Bill of Materials) is a document that lists all the components of a software product, including its dependencies and associated metadata. SBOMs can be used for many purposes, such as tracking software licenses, identifying and addressing security vulnerabilities, and ensuring regulatory compliance.

You can find the current SBOM for CVE-BIN-TOOL which is updated weekly here

Language Specific checkers

A number of checkers are available for finding vulnerable components in specific language packages.

Java

The scanner examines the pom.xml file within a Java package archive to identify Java components. The package names and versions within the archive are used to search the database for vulnerabilities.

JAR, WAR and EAR archives are supported.

Javascript

The scanner examines the package-lock.json file within a javascript application to identify components. The package names and versions are used to search the database for vulnerabilities.

Rust

The scanner examines the Cargo.lock file which is created by cargo to manage the dependencies of the project with their specific versions. The package names and versions are used to search the database for vulnerabilities.

Ruby

The scanner examines the Gemfile.lock file which is created by bundle to manage the dependencies of the project with their specific versions. The package names and versions are used to search the database for vulnerabilities.

R

The scanner examines the renv.lock file which is created by renv to manage the dependencies of the project with their specific versions. The package names and versions are used to search the database for vulnerabilities.

Go

The scanner examines the go.mod file which is created by mod to manage the dependencies of the project with their specific versions. The package names and versions are used to search the database for vulnerabilities.

Swift

The scanner examines the Package.resolved file which is created by the package manager to manage the dependencies of the project with their specific versions. The package names and versions are used to search the database for vulnerabilities.

Python

The scanner examines the PKG-INFO and METADATA files for an installed Python package to extract the component name and version which are used to search the database for vulnerabilities. Support for scanning the requirements.txt file generated by pip is also present.

Support for Version Range (~=) in requirements.txt

The CVE binary tool supports version ranges specified with ~= in your requirements.txt file. This allows you to define a compatible version range for your Python project. The CVE binary tool utilizes pip install --dry-run to seamlessly handle and interpret version ranges specified with ~=. This ensures effective analysis of potential updates without the need for manual parsing of ~=. Note that --dry-run will give “what you get if you installed this requirements list today” so that’s what the scan results will show. We do not attempt to retrieve CVEs for all possible versions in that range. If you want to check a specific version within that range (such as the very first allowed one) you would need to use a separate requirements.txt file with that version frozen.

The tool supports the scanning of the contents of any Wheel package files (indicated with a file extension of .whl) and egg package files (indicated with a file extension of .egg).

The --package-list option can be used with a Python dependencies file requirements.txt to find the vulnerabilities in the list of components.

Perl

The scanner examines the cpanfile file within a perl application to identify components. The package names and versions are used to search the database for vulnerabilities.

The cpanfile must specify the version data for the vulnerability scanner to work. At this time packages without versions will be ignored. (Patches welcome to improve this behaviour in future!)

Here’s an example of what a cpanfile might look like.

PHP

The scanner examines the composer.lock file within a PHP application to identify components. The package names and versions are used to search the database for vulnerabilities. Packages that have a dev version are ignored.

Here’s an example of what a composer.lock file might look like.

Dart

The scanner examines the pubspec.lock file, made by Dart’s pub tool for managing project dependencies and versions. The package names and versions are used to search the database for vulnerabilities.

Here’s an example of what a pubspec.lock file might look like.

Feedback & Contributions

Bugs and feature requests can be made via GitHub issues. Be aware that these issues are not private, so take care when providing output to make sure you are not disclosing security issues in other products.

Pull requests are also welcome via git.

Security Issues

Security issues with the tool itself can be reported to Intel’s security incident response team via https://intel.com/security.

If in the course of using this tool you discover a security issue with someone else’s code, please disclose responsibly to the appropriate party.

CSV2CVE

This tool takes a comma-delimited file (.csv) with the format vendor,product,version and queries the locally stored CVE data (the same data used by the CVE Binary Tool) to give you a list of CVEs that affect each version listed.

This is meant as a helper tool for folk who know the list of product being used in their software, so that you don’t have to rely on binary detection heuristics. There exist other tools that do this, but it seemed potentially useful to provide both in the same suite of tools, and it also saves users from having to download two copies of the same data.

At the moment, you must use the exact vendor and product strings used in the National Vulnerability Database. You can read more on how to find the correct string in the checker documentation. Future work could extend this to use the mappings already in the CVE Binary Tool or to use other mappings such as common linux package names for a given distribution. (Contributions welcome!)

Note: For backward compatibility, we still support csv2cve command for producing CVEs from csv but we recommend using new --input-file command instead.

Running the tool:

csv2cve

If you are trying to run a local copy from source, you can also use python -m cve_bin_tool.csv2cve

Additional Options:

Output options:
    -l {debug,info,warning,error,critical}, --log {debug,info,warning,error,critical}
                            log level. The default log level is info
Functional options:
    -u {now,daily,never}, --update {now,daily,never}
                            update schedule for NVD database. Default is daily. 

Example .csv file:

Note that this does require that the first row be vendor,product,version so that the csv parser can do the right thing. You can have the columns in a different order and/or include other information, but it needs those 3 columns to work.

vendor,product,version
libjpeg-turbo,libjpeg-turbo,2.0.1
haxx,curl,7.59.0
haxx,libcurl,7.59.0
wontwork,no,7.7

Example output:

$ python -m cve_bin_tool.csv2cve test.csv

╔══════════════════════════════════════════════════════════════════════════════╗
║                               CVE BINARY TOOL                                ║
╚══════════════════════════════════════════════════════════════════════════════╝

 • cve-bin-tool Report Generated: 2020-08-03  10:14:11
┌───────────────┐
│ NewFound CVEs │
└───────────────┘
┌───────────┬─────────┬─────────┬────────────┬──────────┐
│ Vendor    │ Product │ Version │ CVE Number │ Severity │
├───────────┼─────────┼─────────┼────────────┼──────────┤
│ wontwork  │ no      │ 7.7     │ UNKNOWN    │ UNKNOWN  │
└───────────┴─────────┴─────────┴────────────┴──────────┘
┌─────────────────┐
│ Unexplored CVEs │
└─────────────────┘
┌────────────────┬────────────────┬─────────┬───────────────────┬───────────┐
│ Vendor         │ Product        │ Version │ CVE Number        │ Severity  │
├────────────────┼────────────────┼─────────┼───────────────────┼───────────┤
│ haxx           │ libcurl        │ 7.59.0  │ CVE-2018-14618    │ CRITICAL  │
│ haxx           │ libcurl        │ 7.59.0  │ CVE-2018-16890    │ HIGH      │
│ haxx           │ libcurl        │ 7.59.0  │ CVE-2019-3822     │ CRITICAL  │
│ haxx           │ libcurl        │ 7.59.0  │ CVE-2019-3823     │ HIGH      │
│ haxx           │ libcurl        │ 7.59.0  │ CVE-2019-5436     │ HIGH      │
│ haxx           │ curl           │ 7.59.0  │ CVE-2018-0500     │ CRITICAL  │
│ haxx           │ curl           │ 7.59.0  │ CVE-2018-1000300  │ CRITICAL  │
│ haxx           │ curl           │ 7.59.0  │ CVE-2018-1000301  │ CRITICAL  │
│ haxx           │ curl           │ 7.59.0  │ CVE-2018-16839    │ CRITICAL  │
│ haxx           │ curl           │ 7.59.0  │ CVE-2018-16840    │ CRITICAL  │
│ haxx           │ curl           │ 7.59.0  │ CVE-2018-16842    │ CRITICAL  │
│ haxx           │ curl           │ 7.59.0  │ CVE-2019-5443     │ HIGH      │
│ haxx           │ curl           │ 7.59.0  │ CVE-2019-5481     │ CRITICAL  │
│ haxx           │ curl           │ 7.59.0  │ CVE-2019-5482     │ CRITICAL  │
│ libjpeg-turbo  │ libjpeg-turbo  │ 2.0.1   │ CVE-2018-19664    │ MEDIUM    │
│ libjpeg-turbo  │ libjpeg-turbo  │ 2.0.1   │ CVE-2018-20330    │ HIGH      │
└────────────────┴────────────────┴─────────┴───────────────────┴───────────┘

How To Guides

How do I create a custom theme for the HTML Report?

CVE Binary Tool provides HTML Report as an output type and although the Report design will work for most of the users it might be the case that we want to update the Report Design according to our needs. So in this tutorial, we will be discussing on how to customise the HTML Report.

CVE Binary Tool provides the functionality to edit report components which we can use to redesign or change the report. CVE Binary Tool uses Object Oriented Programming approach for redesigning that means we need to overwrite files to update the design.

Example: If we want to update the dashboard then we only need to provide dashboard.html file. It will update the dashboard design as specified in the given file. All the remaining design will be as it is.

Before we start let’s discuss the requirements. So first and the most important requirement is that we must know Jinja because cve-bin-tool uses that as its templating engine. We don’t need the advance concepts but knowledge of jinja variables {{ }} and jinja block {% %} is a must. For more info see Jinja Basics. Second we must setup a directory to work with. So let’s start by creating a new directory.

This guide assumes that you are using the version 1.1 or above of cve-bin-tool.

Setting up the directory

Before we start customising the report we have to set up our work directory. Work directory or root directory will contain all the configuration files for components we want to update.

We first need to set up our root directory and then we need to create config folders inside this root directory.

steps to setup directory:

  1. Create a root directory anywhere on your computer. We can name this directory whatever we want. I will create a new directory named my_theme because I want to store my config files there.

user@ubuntu: ~$ mkdir my_theme

user@ubuntu: ~$ cd my_theme/
  1. Create a new config folder templates. Config folders are simple folders but with a specified name. Note that the config folder name must match with templates otherwise it will not overwrite components.

user@ubuntu: ~/my_theme$ mkdir templates

user@ubuntu: ~/my_theme$ cd templates/

  

# Actual Path After the Steps

user@ubuntu: ~/my_theme/templates$

This will set up our templates config folder( templates directory ) and now we are ready to start customising the HTML Report.

Setting up the Files

Now as we have set up our templates folder we will create files that are needed for the report redesign. CVE Binary Tool allows customisation of 4 basic templates. We only need to implement only those templates that we want to overwrite.

  1. base.html

  2. dashboard.html

  3. row_cve.html

  4. row_product.html

These files will control the structure and design of the report. We’ll discuss in detail on what things we need to consider while creating these files and we’ll also discuss which files correspond to which part of the report. But before that let’s create those files.

I’ll create those files using terminal but you can also create them with the help any File Manager or Text Editor.

user@ubuntu: ~/my_theme/templates$ touch base.html

user@ubuntu: ~/my_theme/templates$ touch dashboard.html

user@ubuntu: ~/my_theme/templates$ touch row_cve.html

user@ubuntu: ~/my_theme/templates$ touch row_product.html

We can confirm that using ls in the current directory

user@ubuntu: ~/my_theme/templates$ ls

base.html

dashboard.html

row_cve.html

row_product.html

HTML Report with a custom theme can be generated after creating these files and providing the --html-theme argument with the root directory path.

Now we’ll discuss in detail to see what is the role of each file and how to customise that according to our needs.

row_cve.html

Role:

Each CVE has a unique number associated with it called CVE Number and a severity level measuring the level of severity( Critical, High, Medium, Low). Apart from that a small description of CVE is also present. The row_cve.html handles all the information about CVE and design. Design info includes component design for a single cve and it must not be a full HTML. Full html include <html>, <head> <body> tags.

Example of half html

<!-- example html file -->
<div>
	<h2> I'm not a full html because I don't have head and body </h2>
	<p> This is a example code for half-html </p>
</div>
How to customise?

For customising we need to overwrite the row_cve.html. We need to provide this file inside the templates directory. We have already created this file inside our templates directory if you are following along. We need to include some jinja variables in row_cve.html to include the cve details.

Jinja Variables Implementation Function
{{ cve_number }} required Provides CVE Number
{{ severity}} required Provides CVE Severity ("CRITICAL", "HIGH", "MEDIUM", "LOW")
{{ description }} required Provides a small summary of CVE
{{ var_id }} optional Provides a unique html tag id for each CVE.

For more help, you can take a look at cve-bin-tool’s own row_cve.html template implementation.

<!-- CVE Binary Tool's  row_cve.html  -->

<!-- for each cve in CVE list we will have this row-->
<div  class="card listCVE bg-{{ severity }} text-color-main shadow-sm">
	<div  class="row text-left m-t-5 m-b-5">
		<div  class="col-12 col-lg-5 p-t-10 ">
			<h6  class="m-l-10">{{ cve_number }}</h6>
		</div>
		<div  class="col-7 col-lg-4 p-t-10 ">
			<h6  class="m-l-10">Severity: {{ severity }}</h6>
		</div>
		<div  class="col-5 col-lg-3 text-center">
			<button  class="btn borderButton text-color-main"  data-toggle="collapse"  data-target="#info{{ var_id }}">more info</button>
		</div>
	</div>

	<!-- Hidden Data That we want to show -->
	<div  id="info{{ var_id }}"  class="collapse bg-white"  data-parent="#accord{{ fix_id }}">
		<p  class="summary">{{ description }} <a  href="https://nvd.nist.gov/vuln/detail/{{ cve_number}}" target="_blank" rel="noopener noreferrer">..read more</a></p>
	</div>

</div>
row_product.html

Role:

Each product has one or more CVE associated with it. It also contains information about the Vendor, Version and the name of the Product along with the cve count and a Product Analysis graph based on CVEs. The list of CVEs contains the data rendered with the template row_cve.html.

How to customise?

For customising we need to overwrite the row_product.html. We need to provide this file inside the templates directory. We have already created this file inside our templates directory if you are following along. We need to handles the following jinja variables in the row_product.html. Again this should not be a full-html.

Jinja Variables Implementation Function
{{ vendor }} required Vendor name
{{ name}} required Product name
{{ version }} required Product version
{{ cve_count }} required Number of CVEs in product
{{ list_cves }} required List of CVEs in Product rendered using the row_cve.html
{{ severity_analysis }} optional Pie chart showing the severity level count
{{ fix_id }} optional Provides a unique html tag id for each Product.

For more help, you can take a look at cve-bin-tool’s own row_product.html template implementation.

<!-- CVE Binary Tool's row_product.html -->
<!-- Header for the Product Row [VENDOR, PRODUCT, VERSION, NUMBER_OF_CVES] -->

<div  class="card text-center pHeading text-color-main p-t-5 product">
	<div  class="row">
		<a  class="stretched-link"  data-toggle="collapse" href="#div{{ fix_id }}"></a>
		<!-- Vendor -->
		<div  class="col-6 col-lg">
			<h5  class="font-weight-light">Vendor: {{ vendor }}</h5>
		</div>
		<!-- Product -->
		<div  class="col-6 col-lg">
			<h5  class="font-weight-light">Product: {{ name }}</h5>
		</div>
		<!-- Version -->
		<div  class="col-6 col-lg">
			<h5  class="font-weight-light">Version: {{ version }}</h5>
		</div>
		<!-- Total number of Known vulnerability -->
		<div  class="col-6 col-lg">
			<h5  class="font-weight-light">Number of CVE's: {{ cve_count }}</h5>
		</div>
	</div>
</div>

<!-- Product CVEs start from here -->

<!-- cve row contains ListCVES for each product of specific version and analysis Chart-->
<div  id="div{{ fix_id }}"  class="hideme">
	<div  class="row ">
		<!-- List CVES -->
		<div  class="col-12 col-md-7 col-lg-8"  id="accord{{ fix_id }}">
			{{ list_cves }}
		</div>

		<!-- Analysis Chart for each product version -->
		<div  class="col-12 col-md-5 col-lg-4">
			<div  class="card analysis m-t-10">
				<div  class="card-header text-center bg-header-dash">
					<h6>Severity Analysis of {{ name }} {{ version }}</h6>
				</div>
				<div  class="card-body">
					{{ severity_analysis }}
				</div>
			</div>
		</div>
	</div>
</div>
dashboard.html

Role:

The dashboard is the main showcase area with two graphs. One with the details of the number of products that were found and the other contains the information about the number of CVEs in the products that were found.

How to customise?

The dashboard.html is to be present in our work directory under the templates folder. It must not be a full-html and must handle the following jinja variable.

Jinja Variables Implementation Function
{{ graph_products }} required Pie Chart with data of Products Vulnerable and with no known vulnerability
{{ graph_cves}} required Bar Graph to show CVE count in each product and version
{{ total_files }} optional Total Number of Files that were scanned
{{ products_with_cve }} optional No of products that were found in the scan

For more help, you can take a look at cve-bin-tool’s own dashboard.html template implementation.

<!-- CVE Binary Tool's dashboard.html-->

<!-- Main Information Dashboard -->
<div  class="row m-b-20">
	<!-- Left Col -->
	<div  class="col-12 col-md-4">
	<!-- left-card / Card to show total scanned files and vulnerable products -->
		<div  class="card text-color-main shadow-lg bg-white rounded">
			<!-- Card Header -->
			<div  class="card-header text-color-main text-center bg-header-dash">
				<div  class="row justify-content-sm-centre">
					<div  class="col-6">
						<h6>Scanned Files: {{ total_files }}</h6>
					</div>
					<div  class="col-6">
						<h6>Found {{ products_with_cve }} Products</h6>
					</div>
				</div>
			</div>
			<!-- Card Body -->
			<div  class="card-body">
			<!-- SVG Graph That display total packages with known vulnerability -->
				{{ graph_products }}
			</div>
		</div>
	</div>
	<!-- Right Col -->
	<div  class="col-12 col-md-8">
		<!-- Graph to show Total CVE's in each product -->
		<div  class="card text-color-main shadow-lg bg-white rounded">
			<div  class="card-header bg-header-dash">
				<h6>Product CVES's</h6>
			</div>
			<div  class="card-body">
				{{ graph_cves }}
			</div>
		</div>
	</div>
</div>
base.html

Role:

As the name suggests base.html is the actual base for all other templates and the rendered results of each template are included in this base template. It also holds all the scripts and CSS files and is required to be a full-html.

How to customise?

As such, there is no restriction on how to customise base.html but we need to handle some jinja variables otherwise it will not render properly. Also, we must make sure that plotly.js is included at the top otherwise the graphs will not render.

Here is the list of jinja variables that we need to provide in the template.

Jinja Variables Implementation Function
{{ script_plotly}} required JavaScript File for Plotly.js which is needed for Graph Generation
{{ dashboard }} required This will contain the dashboard.html in rendered form
{{products_found}} required This will have all the products that are found during the scan and rendered in product_cve.html
{{script_jquery}} required JQuery.js file
{{script_bootstrap}} required Bootstrap.js file
{{ style_bootstrap}} required bootstrap CSS file
{{ date }} optional date of report generation
{{ style_main }} optional Your own CSS implementation
{{ script_main }} optional Your own JavaScript implementation

For more help, you can take a look at cve-bin-tool’s own base.html template implementation.

<!DOCTYPE  html>

<html  lang="en">
<head>
	<meta  charset="UTF-8">
	<meta  name="viewport"
		content="width=device-width, initial-scale=1.0, user-scalable=0,shrink-to-fit=no, maximum-scale=1, minimum-scale=1">
	<title>CVE-BIN-TOOL | Descriptive Report</title>

	<!-- JavaScript for Plotly -->
	<script> {{ script_plotly }}</script>
	<!-- Bootstrap CSS -->
	<style>
		/* Bootstrap */
		{{ style_bootstrap }}
		/* Mystylesheet */
		{{ style_main }}
	</style>
</head>
<body>
	<div  class="container-fluid">
	<!-- Name of the tool and Date at which is generated -->
		<div  class="card bg-title text-light m-t-20 m-b-20">
			<div  class="card-header">
				<div  class="row justify-content-sm-centre ">
					<!-- Name of the Tool -->
					<div  class="col-sm-auto col-sm ">
						<h4  class="font-weight-light">CVE Binary Tool: Descriptive Report</h4>
					</div>
					<!-- Report generation date -->
					<div  class="col-sm">
						<h4  class="text-right font-weight-light"> {{ date }}</h4>
					</div>
				</div>
			</div>
		</div>
		<!-- Block for Dashboard -->
		{{ dashboard }}

		<!-- Header All Products -->
		<div  class="card bg-title text-light m-t-20 m-b-15">
			<div  class="card-header">
				<div  class="row">
					<div  class="col-9">
						<h5  class="font-weight-light p-t-5">Products With Known Vulnerability</h5>
					</div>
					<div  class="col-3 text-right">
						<button  class="btn btn-filter borderButton text-color-main"  data-toggle="collapse" data-target="#filterdiv">Search Data</button>
					</div>
				</div>
			</div>
		</div>
		<div  class="row collapse text-center"  id="filterdiv">
			<div  class="offset-4 col-4 onset-4">
				<div  class="active-pink-4 mb-4">
					<input  id="searchInput"  class="form-control"  type="text"  placeholder="Search"  aria-label="Search">
				</div>
			</div>
		</div>
		<!-- List of all the products -->
		<div  id="listProducts">
			{{ products_found }}
		</div>
	</div>
	<!-- Jquery -->
	<script>{{ script_jquery }}</script>
	<!-- Bootstrap JS -->
	<script>{{ script_bootstrap }}</script>
	<script>
		{{ script_main }}
	</script>
</body>
</html>

Adding and updating custom CSS and JavaScript files

CVE Binary Tool uses the bootstrap 4 to style the templates but we might want to use the latest bootstrap version available( bootstrap 5 is in its early stage at the time when I’m writing this tutorial ). It might also be the case that we want to include our custom CSS files and even js files.

Updating CSS and JS files

CVE Binary Tool allows us to update the CSS and JS files in the same manner as we update the templates. So we just need to create a new config folder inside our work directory(In our case my_theme) named css to update the CSS files and other named js to update the javascript files.

Here is the list of files that we can update.

CSS FILES

File name

Functionality

bootstrap.css

Bootstrap.css file for the report

main.css

Custom CSS file for the report

Example: If we want to update the main.css file we’ll create a main.css file inside the css folder under the work directory(my_theme).

JavaScript FILES

File name

Functionality

bootstrap.js

Bootstrap.js file for the report

plotly.js

Plotly.js is used for graph generation

jquery.js

JQuery file for the report

main.js

Custom JavaScript for the report

Example: If we want to update the main.js file we’ll create a main.js file inside the js folder under the work directory(my_theme).

Adding CSS and JavaScript

Apart from the given files, we might want to include other Popular JS and CSS files like we might want to add Font Awesome, Popper.js or any other custom CSS or js file.

So to add custom styles we need to include them in the base.html inside the templates directory. So the implementation of base.html is a must. If we don’t want to update the cve-bin-tool’s base.html then we can copy the template and paste that in the templates folder of our work directory and then we can include our CSS and js files.

There are two methods to include CSS and js

  1. Use CDNs to include js and CSS files

  2. Copy the contents of CSS and JS files directly inside the base.html. This method is recommended as it will allow the report to work even in complete offline mode(No Internet).

We know that we must maintain different HTML, CSS and js files but because we want to generate a single report file so need to include everything in a single file.

For more help or suggestion you can contact our community.

How to scan a docker image?

There are couple of ways to scan a docker image using cve-bin-tool.

  1. You can scan a docker image by installing and running cve-bin-tool inside a docker container.

  2. You can export the directory on host and scan it on host.

We are going to scan /usr/bin directory of ubuntu:latest docker image for demonstration purpose but you can use same recipe to scan directory of your interest.

Install and run CVE Binary Tool inside container

Let’s first create a docker instance of the image we want to scan using following command:

docker run -it -d --name cve_scan ubuntu  --entrypoint bash 

This will create new instance of ubuntu image and run it in the background. You can check if your container is running or not using docker ps.

Note: you may need to use sudo if current user isn’t in the docker group.

Now let’s go inside the container using the docker exec command and install python in it.

docker exec -it cve_scan bash

In this example we have defined container name as cve_scan. You will get a random name if you have not defined while running the container initially.

Update the container and install python3 on it.

apt-get update
apt-get install python3
apt-get install python3-pip

Note: this step is distro specific if your container is based on different distro (Ex: centos) checkout official documentation of that specific distro for installing python3 in it.

Now let’s install cve-bin-tool in our container.

pip3 install cve-bin-tool

This will install latest version of cve-bin-tool from PyPI.

You can also install latest development version from our github repository using following command

pip3 install git+https://github.com/intel/cve-bin-tool

After all the things done check the version of cve-bin-tool using the command.

cve-bin-tool -V

If there is output then You have installed cve-bin-tool successfully in the docker container.

Now let’s scan /usr/bin directory and export report to the host using following command.

cve-bin-tool /usr/bin -f csv -o usr_bin_cve.csv

This will take sometime and after generation of the report, you have to export it to the host. You first need to exit current docker session by typing exit in the container terminal. Now let’s copy report from container to the host.

docker cp cve_scan:~/usr_bin_cve.csv ~/Documents/usr_bin_cve.csv

This will save CVE report of scanned docker directory in the ~/Documents/usr_bin_cve.csv.

Export directory from container and scan

Assuming, you already have created docker instance named cve_scan as mentioned above. You can export directory you want to scan to the host and scan there.

docker cp cve_scan:/usr/bin/ ~/scan

This will copy all files and directories from /usr/bin to /scan and now you can scan scan directory with cve-bin-tool normally.

Note: You may want to use docker cp -a if you want to copy all uid/gid info.

cve-bin-tool scan [OPTIONS]

Note: This method assumes you already have installed cve-bin-tool on host. If you haven’t install it with pip3 install cve-bin-tool.

Both of the above mentioned methods will help you scan a docker image and you can choose one over another. Second method is comparatively easier than first but has overhead of copying all data from container to host while first method requires you to install cve-bin-tool in docker container which can take around 10 minutes. You can automate both processes with simple bash script.

How do I use CVE Binary Tool in an offline environment?

The cve-bin-tool can be used in offline environments which do not have direct access to the internet to download the latest vulnerability databases.

Prepare the vulnerability database for offline use

To download the vulnerability database for use in an offline environment, ensure that cve-bin-tool is installed on an internet-connected system.

Run the tool to obtain the latest version of the vulnerability database

$ cve-bin-tool --update now

NOTE The tool will error with InsufficientArgs because no directory was specified for a scan. This is expected behaviour.

Export the database

Run the tool to export the latest version of the vulnerability database.

$ cve-bin-tool --export <filename>

Transfer the vulnerability database file into a directory in the offline environment

The way of transfer depends on the environment.

Import the vulnerability database file on the offline system

Run the tool to import the transferred copy of the vulnerability database.

$ cve-bin-tool --import <filename>

The cve-bin-tool will fail to operate in offline mode if a vulnerability database is not present on the system.

Run cve-bin-tool with –offline option

In an offline environment, specify the --offline option when running a scan so that cve-bin-tool doesn’t attempt to download the latest database files or check for a newer version of the tool. The --offline option is equivalent to specifying --update never and --disable-version-check options.

Maintenance Updates

In an offline environment, it is important to update the vulnerability database on a regular basis as often as you feel appropriate, so that the scanner can continue to detect recently-identified vulnerabilities. If any changes to CVE data is required (e.g. to remove false positives), you might also want to create and copy over a triage data file for usage. The time of the latest database update is reported whenever a scan is performed.

It is important to periodically check if the cve-bin-tool has also been updated as this check cannot be performed within an offline environment.

Best practices for running multiple scans at once

If you’re running multiple instances of cve-bin-tool at once, you could potentially cause a race condition where multiple processes are trying to update the database from nvd at the same time. This is not ideal.

To avoid this, you should use a single command to run the nvd update, then turn off the updater in all other copies.

Step 1: Update

To update (without scanning) you can use the following command:

cve-bin-tool -u now

We recommend once per day, but this can be more frequently or less frequently depending on your needs. Ideally, you want to be sure this completes before you kick off any other scans, so that you aren’t checking against a partial database.

Step 2: Scan

Each parallel instance of cve-bin-tool can then be invoked as follows:

cve-bin-tool -u never $path_to_directory_or_file

NVD CVE Retrieval API

The CVE API is the next stage in providing up to date vulnerability information for NVD data consumers. The results from this API are updated as quickly as NVD website (unlike the traditional feeds which have explicit update interval of once per day).

This can be also used as a backup if the current JSON feed retrieval interface is removed from the NVD website.

Note: This API retrieval is slower in comparison to the traditional method.

You can read more about this here

The NVD API is enabled by default or you can explicitly use -n api or --nvd api:

python -m cve_bin_tool.cli -n api

A major benefit of using this NVD API is incremental updates.

What are Incremental Updates?

With the help of this REST API, we can fetch just the newly added/modified NVD data using the timestamp of your current local database copy. This will fetch only the CVE entries for which any vulnerability or product string was modified or published later than the above-mentioned timestamp. This can save users a lot of time and internet bandwidth.

How to use Incremental Updates?

You can use pre-existing -u latest parameter along with the -n api. This will simply update your local database and cache copy with the newly published and modified NVD entries.

python -m cve_bin_tool.cli -u latest  -n api

How to use intermediate reports

Let’s consider a case where multiple groups have done triage separately and want to merge their outputs in a single report. We can do this by saving scans in form of intermediate reports and merge them whenever required.

Create Intermediate reports

To create an intermediate report on a scan for path /home/code/backend/, you can use:

python -m cve_bin_tool.cli -a /home/reports/backend.json /home/code/backend/

Here we are saving the intermediate report in /home/reports/backend.json
Alternatively, you can just use the directory path omitting the filename. Example:

python -m cve_bin_tool.cli -a /home/reports/ -t frontend /home/code/frontend/

CVE-Binary Tool will generate a filename with the default naming convention which is: "append.YYYY-MM-DD.hh-mm-ss.json"

Note: You can also use -t --tag if you want to add a unique tag inside your intermediate report. By default it is empty and stored as "".

Intermediate report format

{
    "metadata": {
        "timestamp": "2021-06-17.00-00-30",
        "tag": "",
        "scanned_dir": "/home/code/backend",
        "products_with_cve": 139,
        "products_without_cve": 2,
        "total_files": 49
    },
    "report": [
        {
            "vendor": "gnu",
            "product": "gcc",
            "version": "9.0.1",
            "cve_number": "CVE-2019-15847",
            "severity": "HIGH",
            "score": "7.5",
            "cvss_version": "3",
            "paths": "/home/code/backend/glib.tar.gz,/home/code/backend/gcc.tar.gz",
            "remarks": "NewFound",
            "comments": ""
        },
        ...
    ]
}

Adding triage information to a merge report

Merged reports can be used to store and/or share triage information about the vulnerabilities that have been found.

To add triage, you can open up the json file in a text editor or json editor of your choice to add any changes you need.

The “remarks” section allows 6 values:

  1. NewFound

  2. Unexplored

  3. Confirmed

  4. Mitigated

  5. False Positive

  6. Not Affected

More details such as how a CVE was mitigated or why it can be ignored can be added into the “comments” section. Other fields such as severity and score can also be updated if necessary.

Merge intermediate reports

You can merge multiple intermediate reports created using -m --merge

python -m cve_bin_tool.cli -m /home/reports/

-m --merge takes a comma-separated string. So, you can also pass filename(s) directly:

python -m cve_bin_tool.cli -m /home/reports/backend.json,/home/reports/append.2021-06-17.00-00-30.json

If you want to save the output in some other format (By default, it is console). You can also use -f --format and -o --output-file while merging intermediate reports. For example, If you want to generate an HTML report:

python -m cve_bin_tool.cli -m /home/reports/ -f html -o /home/reports/merged_intermediate.html

Filter Intermediate Reports

Let’s consider a case where a user has multiple intermediate reports stored at a single path. But the user wants to merge only selected reports. We can do this by filtering intermediate reports based on the tag.

How to filter Intermediate reports?

Suppose you have multiple intermediate reports stored at a single path.

path
├── intermediate.cve-bin-tool.2021-06-02.01-17-48.json[weekly]
├── intermediate.cve-bin-tool.2021-06-09.02-39-43.json[weekly]
├── intermediate.cve-bin-tool.2021-06-16.23-44-35.json[weekly]
├── intermediate.cve-bin-tool.2021-06-23.23-44-49.json[weekly]
├── intermediate.cve-bin-tool.2021-06-24.23-45-08.json[daily]
├── intermediate.cve-bin-tool.2021-06-25.23-45-08.json[daily]
└── intermediate.cve-bin-tool.2021-06-26.23-45-08.json[daily]

0 directories, 7 files

Note: You can specify tags while generating intermediate reports using -t --tag. For this example, we have assumed that the intermediate reports contain tag {weekly or daily}

We want to merge the weekly generated report to plot the week-wise timeline trace as an HTML report. We can have some other use cases as well.
To filter out the intermediate reports, use:

python -m cve_bin_tool.cli -F weekly -m /path -f html

This will generate a merged report from these files -

path
├── intermediate.cve-bin-tool.2021-06-02.01-17-48.json[weekly]
├── intermediate.cve-bin-tool.2021-06-09.02-39-43.json[weekly]
├── intermediate.cve-bin-tool.2021-06-16.23-44-35.json[weekly]
└── intermediate.cve-bin-tool.2021-06-23.23-44-49.json[weekly]

Alternatively, users can filter out intermediate reports which are generated by multiple teams if they have specified distinguishable tags. If we have intermediate reports {backend and frontend}. We can simply use:

python -m cve_bin_tool.cli -F backend -m /path 

This will generate a vulnerability report for all the backend related binaries.

How do I run CVE Binary Tool in GitHub Actions?

CVE Binary Tool can be run in GitHub Actions in order to scan your project dependencies for any CVEs. To understand what GitHub Actions are and how they work, you can refer to the official documentation.

Workflows in GitHub Actions are defined in YAML files in your code repository in the .github/workflows directory. These workflows are triggered whenever some events are set off in the repository, for example, whenever a Pull Request is made.

Adding the workflow to your repository

To add the tool to your workflow, place the cve_scanner_gh_action.yml file, or copy it from below into the .github/workflow directory of your repository and you should be good to go!

cve_scanner_gh_action.yml:

name: CVE scanner
on:
  # You can customize this according to your need.
  - push
  - pull_request
jobs:
  build_and_scan:
    runs-on: ubuntu-22.04
    steps:
      # Get date utility for caching database.
      - name: Get Date
        id: get-date
        run: |
          echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
        shell: bash
      # Let's first download dependencies for this action.
      - uses: actions/checkout@v2
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.x'
      # This second step is unnecessary but highly recommended because
      # It will cache database and saves time re-downloading it if database isn't stale.
      - name: get cached python packages
        uses: actions/cache@v3
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
          restore-keys: |
            ${{ runner.os }}-pip-
      - name: get cached database
        uses: actions/cache@v3
        with:
          path: cache
          key: Linux-cve-bin-tool-${{ steps.get-date.outputs.date }}
      - name: Install CVE Binary Tool
        # We are using latest development version of CVE Binary Tool
        # because current PyPI version don't have features like config file support,
        # generating HTML report etc.
        run: |
          [[ -e cache ]] && mkdir -p .cache && mv cache ~/.cache/cve-bin-tool
          pip install git+https://github.com/intel/cve-bin-tool@main
      # In case you prefer current PyPI version, you need to hard code CLI options
      # for cve-bin-tool in the action itself and have to use CSV or JSON as output format.
      # pip install cve-bin-tool
      - name: build package
        # Here, we are building Python wheel for this example.
        # You need to replace this with your build process.
        run: |
          pip install wheel
          python setup.py bdist_wheel
      - name: Scan built package
        # Here, we are scanning built wheel which is situated in /dist directory
        # Python stores built packages in /dist directory.
        # You need to replace it with the directory where you have stored built package
        run: cve-bin-tool dist -f html -o cve-bin-tool-report.html -x
        #  Alternatively if you have written config file for cve-bin-tool you can use following command
        #  cve-bin-tool -C path/to/cve_bin_tool_config.toml
        continue-on-error: true
      # You need to set continue_on_error: true because CVE Binary Tool sets number of cves
      # as exit code. And GitHub terminates action when process produces
      # nonzero exit code status.
      - name: Upload report as an artifact
        # This will upload generated report as an GitHub artifact which you can download later.
        uses: actions/upload-artifact@v2
        with:
          name: cve_report
          path: 'cve-bin-tool-report.html'

Summary of the workflow

The workflow file itself is pretty well-commented and explained. It should be easy to understand what it does by reading through it.

  1. On every push or pull request, the workflow is triggered (this is considered an event). On an Ubuntu virtual environment, CVE Binary Tool is set up and installed.

  2. After this, a Python Wheel is built for your project’s requirements and dependencies. If your build process is different, then you should replace this step with your build process.

  3. The tool then scans the built wheel situated in the /dist directory. Again, if your build process is different, you are going to need to change this step too.

  4. Now the workflow will upload the generated HTML report as GitHub artifact to refer to later.

How do I use CVE Binary Tool to scan a SBOM?

The cve-bin-tool can be used to scan a software bill of materials (SBOM) file to identify the vulnerabilities within the packages identified in the file.

SBOM support

The cve-bin-tool supports SBOMs in the following formats

SBOM Type Version Format
SPDX 2.2 TagValue
SPDX 2.2 RDF
SPDX 2.2 JSON
SPDX 2.2 YAML
SPDX 2.2 XML
CycloneDX 1.3-1.5 XML
CycloneDX 1.3-1.5 JSON
SWID See Note XML

Details of the formats for each of the supported SBOM formats are available for SPDX , CycloneDX and SWID

For SPDX SBOM files, it is assumed that the name of a Package precedes the version information for the package. Only modules with a package name and associated version information shall be processed.

The SWID format follows the ISO/IEC 19770-2:2015 standard.

Usage

To scan a SBOM, run the tool as shown (other parameters can be specified as required e.g. format)

$ cve-bin-tool --sbom <sbom type> --sbom-file <sbom filename>

To determine the format of the SBOM file, the following filename conventions are followed

SBOM Format Filename extension
SPDX TagValue .spdx
SPDX RDF .spdx.rdf
SPDX JSON .spdx.json
SPDX YAML .spdx.yaml
SPDX YAML .spdx.yml
SPDX XML .spdx.xml
CycloneDX XML .xml
CycloneDX JSON .json
SWID XML .xml

Examples

Scan a SPDX SBOM in TagValue format with the name sbom.spdx

cve-bin-tool --sbom spdx --sbom-file sbom.spdx

If the --sbom option is omitted, the scan defaults to a SPDX SBOM in TagValue format. The above and below examples are equivalent.

cve-bin-tool --sbom-file sbom.spdx

Scan a CycloneDX SBOM in JSON format with the name sbom.json

cve-bin-tool --sbom cyclonedx --sbom-file sbom.json

Scan a SWID SBOM in XML format with the name sbom.xml

cve-bin-tool --sbom swid --sbom-file sbom.xml

Help

In order for vulnerabilities to be identified, the package names and version data must match with the information which is captured within the NVD database. If no vulnerabilities are being reported, adding --log debug to the command line will report the packages and versions of the modules extracted from the SBOM file.

Note that package names should not include spaces and that version numbers should only contain numeric characters (and ‘.’).

Limitations

As some package/version number pairs cannot be resolved to a unique vendor, the reported vulnerabilities may be incomplete or inaccurate.

Interoperability

This feature is known to work with SBOM files generated by tern.

How do I use CVE Binary Tool to generate a SBOM?

The cve-bin-tool can be used to generate a software bill of materials (SBOM) file, which is a file that contains a list of all components detected by the scan in a standardized format.

SBOM support

The cve-bin-tool generates SBOMs in the following formats

SBOM Type Format Filename extension
SPDX TagValue .spdx
SPDX JSON .spdx.json
SPDX YAML .spdx.yaml
SPDX YAML .spdx.yml
CycloneDX JSON .json

Details of the formats for each of the supported SBOM formats are available for SPDX and CycloneDX

Usage

To generate a SBOM, run the tool as shown. See the examples below for details about optional arguments and default values used.

cve-bin-tool --sbom-type <sbom type> --sbom-format <sbom format> --sbom-output <sbom filename>

Examples

Generate a SPDX SBOM in TagValue format with the name sbom.spdx

cve-bin-tool --sbom-type spdx --sbom-format tag --sbom-output sbom.spdx .

If the --sbom-type option is omitted, a SBOM is generated in the SPDX type. If the --sbom-format option is omitted, the format is inferred from the extension of the --sbom-output filename. The above and below examples are equivalent.

cve-bin-tool --sbom-output sbom.spdx

Generate a SPDX SBOM in YAML format with the name sbom.yml

cve-bin-tool --sbom-type spdx --sbom-format yaml --sbom-output sbom.yml

Generate a CycloneDX SBOM in JSON format with the name sbom.json. Note that CycloneDX SBOMs are only generated in JSON, so the --sbom-format option is unnecessary.

cve-bin-tool --sbom-type cyclonedx --sbom-output sbom.json

Scanning installed packages

-L or --package-list option runs a CVE scan on installed packages listed in a package list. It takes a python package list (requirements.txt) or a package list of packages of systems that has dpkg, pacman or rpm package manager as an input for the scan. This option is much faster and detects more CVEs than the default method of scanning binaries.

You can get a package list of all installed packages in

  • a system using dpkg package manager by running dpkg-query -W -f '${binary:Package}\n' > pkg-list.txt

  • a system using pacman package manager by running pacman -Qqe > pkg-list.txt

  • a system using rpm package manager by running rpm -qa --queryformat '%{NAME}\n' > pkg-list.txt

in the terminal and provide it as an input by running cve-bin-tool -L pkg-list.txt for a full package scan.

CVE Binary Tool Release Notes

CVE Binary Tool 3.2

New features from our GSoC 2022 participants:

  • @yashugarg added a large number of tests and work on fuzzing our interfaces

  • @rhythmrx9 added new data sources (we now support advisories from Gitlab, OSV and Redhat as well as NVD)

  • @XDRAGON2002 for the new parsers that allow us to scan things like Ruby Gemfiles, Rust cargo files, and more.

Other interesting features in this release:

  • @ffontaine has added a large number of new checkers, pushing us well over 200 binary checkers.

  • @anthonyharrison has added initial support for NVD API 2.0. Note that at the time this was added the 2.0 version didn’t work with their API keys, so the code behaves accordingly.

Thanks also to @BreadGenie for code review and mentoring support as well as a number of contributions listed below. A special shout out to @b31ngd3v and @metabiswadeep whose first contributions are in this release but they’ve been the first of many, as well as the many other folk who got their first commits in via Hacktoberfest or GSoC or goodfirstissue.dev or however you found us. Thanks to everyone for being part of this release!

CVE Bin Tool pre-release 3.2rc0

Preview release for 3.2.

We’re currently seeing an issue in our testing system where Windows systems are taking a long time to upgrade the database to store additional data source information. Windows users are particularly encouraged to try this pre-release to see if you have any issues!

When updating your database, make sure your NVD_API_KEY is set and you may have better results using -u now to get a fresh database.

CVE Binary Tool 3.1.2

Minor update to force a downgrade of packaging to allow use of LegacyVersion (fixes #2428)

This is intended to be a temporary fix while we finish up the 3.2 release, but I believe we will be able to backport the removal for LegacyVersion without much trouble, so there may be one more release for the 3.1 tree if it looks like 3.2 is going to take more than a week.

Full Changelog: v3.1.1...v3.1.2

CVE Binary Tool 3.1.1

Minor typo necessitated a version bump + new release.

CVE Binary Tool 3.1

This release is dedicated to the person who sent me cookies after I was griping about differences in Python 3.7 error handling on Twitter. They were delicious, thank you! Thanks also to the many new contributors who have joined us as part of Google Summer of Code 2022. You can see many new folk had their first commits in this release!

New Features

  • CVE Binary Tool 3.1 adds support for NVD API keys. An NVD API key allows registered users to make a greater number of requests to the API. At this time, the NVD API documentation says, “The public rate limit (without an API key) is 10 requests in a rolling 60 second window; the rate limit with an API key is 100 requests in a rolling 60 second window.”

    • cve-bin-tool updates once per day by default to limit connections to NVD, but users in shared environments or running more frequent updates have occasionally seen 403 errors due to exceeded rate limits. Using an API key should alleviate those issues going forwards.

  • New support for scanning Java and JavaScript packages has been added. (Yes, this will now detect log4j packages.) The language-specific packages we support now are Java, JavaScript and Python.

  • A new offline flag (--offline) has been added to disable all network requests for use in isolated environments. A guide for using –offline mode can be found here.

  • New support VEX (Vulnerabity Exploitablity Exchange) files. Files could be generated following a scan and then used as a supported triage file.

  • Extractor support has been extended to include WAR, EAR, pkg and zst files.

  • New checkers: Libsrtp, libseccomp, libebml, libsolv

Changed Features

  • Some users had expressed concern that they would prefer not to install the Reportlab dependency on their systems due to security concerns if the library is mis-used, so we no longer install it by default.

    • Users intending to use PDF export can use pip install cve-bin-tool[PDF] to add reportlab to their install. or pip install reportlab if they decide they want it later.

    • Similarly, users can pip uninstall reportlab at any time and cve-bin-tool will continue to function although without the ability to export PDF files. Users can generate their own using pdf reports using print-to-pdf on an HTML report if needed.

  • Python 3.6 support and testing has been dropped as Python 3.6 has reached end of life. (This may affect some users on CentOS.)

CVE Binary Tool 3.1rc3

Full Changelog: v3.1rc2…v3.1rc3

CVE Binary Tool 3.1rc2

Potentially the final release candidate for CVE Binary Tool 3.1. (Note the change in naming scheme to match the pip upload)

CVE Binary Tool 3.1.pre1

Second pre-release. This one has all features expected for release and will undergo some additional validation before final release.

CVE Binary Tool 3.1.pre0

Pre-release for what will eventually be 3.1. There are a few PRs still in progress, and you can see what remains to be updated in the 3.1 milestone. The release notes below are auto-generated by GitHub.

CVE Binary Tool 3.0

The CVE Binary Tool 3.0 release includes improved tools for checking known lists of packages including Linux distributions, improved methods of communication with NVD to get vulnerability data, additional checkers, and significant refactoring to streamline the output.

New feature highlights:

  • SBOM Scanning: CVE Binary Tool can now take Software Bill of Materials (SBOM) files to help users improve their supply chain security data for all known dependencies. The initial feature can handle some versions of SPDX, CycloneDX and SWID formats. More information on SBOM scanning can be found here: https://github.com/intel/cve-bin-tool/blob/main/doc/how_to_guides/sbom.md

  • Known vulnerability information: Users scanning some linux distro packages can now get additional information about fixes available for those platforms.

  • Vulnerability Data: The default method for getting NVD vulnerability lists has been changed. Previously we downloaded full yearly JSON files if anything in the year had changed, the new API allows us to get only the latest changes. Users may see a speedup during the update phase as a result.

  • (Breaking change) Return codes: The return codes used by CVE Binary Tool have changed.

    • A 0 will be returned if no CVEs are found, a 1 will be returned if any CVEs were found (no matter how many), and codes 2+ indicate operational errors. A full list of error codes is available here: https://github.com/intel/cve-bin-tool/blob/main/cve_bin_tool/error_handler.py

    • Previously we returned the number of CVEs found, but this could exceed the expected range for return codes and cause unexpected behaviour.

Thanks especially to our 2021 GSoC students, @BreadGenie, @imsahil007 and @peb-peb whose final GSoC contributions are part of this release.

A full list of changes is available in GitHub. https://github.com/intel/cve-bin-tool/releases/tag/v3.0

Commit messages use the Conventional Commits format.

CVE Binary Tool 2.2.1

Release date: 04 Aug 2021

The 2.2.1 release relaxes the behaviour when file extraction fails, which was causing problems for some users scanning files with .exe and .apk file extensions using the previous release. In 2.2 all extraction fails caused the tool to halt and throw an exception, in 2.2.1 the tool will log a warning and continue.

CVE Binary Tool 2.2

Release date: 08 Jul 2021

The 2.2 release contains a number of bugfixes and improvements thanks to the many students who contributed as part of our Google Summer of Code selection process. Congratulations to @BreadGenie, @imsahil007 and @peb-peb who will be continuing to work with us for the next few months!

New feature highlights:

  • CVE Binary Tool can now be used to get lists of vulnerabilities affecting a python requirements.txt file, as well as lists of packages installed on .deb or .rpm based systems (Thanks to @BreadGenie)

  • Scan reports can now be merged (Thanks to @imsahil007)

  • Reports can now be generated in PDF format (Thanks to @anthonyharrison)

  • A new helper script is available to help new contributors find appropriate patterns for new checkers (Thanks to @peb-peb)

  • Reports can now be generated even if no CVEs are found (Thanks to @BreadGenie)

  • We’ve added rate limiting for our NVD requests (Thanks to @nisamson, @param211, @bhargavh)

There are also a number of new checkers and bug fixes.

Thanks also to @jerinjtitus, @Molkree, @alt-glitch, @CabTheProgrammer, @Romi-776, @chaitanyamogal, @Rahul2044, @utkarsh147-del , @SinghHrmn, @SaurabhK122, @pdxjohnny and @terriko for their contributions to this release.

CVE Binary Tool 2.1.post1

Release date: 27 Apr 2021

Rate limiting temporary fix in response to NVD API update

CVE Binary Tool 2.1

Release date: 07 Dec 2020

This release fixes an issue with jinja2 autoescape breaking the HTML reports and includes some updates to tests.

CVE Binary Tool 2.0

Release date: 12 Nov 2020

This release features code from our three successful Google Summer of Code students!

  • @SinghHrmn made improvements to our output formats, including adding a new HTML human-readable report format. You can try out a demo at https://intel.github.io/cve-bin-tool/

  • @Niraj-Kamdar improved the performance of cve-bin-tool and its tests, provided significant code modernization and added input modes so you can now add and re-use triage data with your scans.

  • @SaurabhK122 added a huge number of new checkers to the tool, both in this release and the previous one.

Thanks also to the mentors who worked with our students this year: @terriko, @pdxjohnny, @meflin, @mdwood-intel and unofficial mentor @anthonyharrison who helped us considerably with real-world feedback.

This release also includes contributions from the following new contributors:

  • @anthonyharrison

  • @imsahil007

  • @chaitanyamogal

  • @Rahul2044

  • @Wicked7000

  • @willmcgugan

  • @kritirikhi

  • @sakshatshinde

CVE Binary Tool 1.1.1

Release Date: 9 Nov 2020

This point release includes fixes so documentation will build and display correctly on readthedocs. There are no functional changes to the code.

CVE Binary Tool 2.0 alpha release

Release Date: 29 Oct 2020

This is an alpha release for people interested in trying out an early preview of 2.0. Major features include performance improvements, triage options, new output modes, and many new checkers thanks to our Google Summer of Code students @Niraj-Kamdar, @SinghHrmn and @SaurabhK122 . Thanks for an incredibly productive summer!

We are expecting to make some documentation improvements before the final release, which we hope to have out next week.

CVE Binary Tool 1.1

Release Date: 29 Oct 2020

This is an alpha release for people interested in trying out an early preview of 2.0. Major features include performance improvements, triage options, new output modes, and many new checkers thanks to our Google Summer of Code students @Niraj-Kamdar, @SinghHrmn and @SaurabhK122 . Thanks for an incredibly productive summer!

We are expecting to make some documentation improvements before the final release, which we hope to have out next week.

CVE Binary Tool 1.0

Release Date: 20 Apr 2020

This release includes major improvements to the way NVD data is used and stored. If you have tried the development tree from GitHub, you may wish to run cve-bin-tool -u now after you upgrade to remove old data.

There are now three output formats:

  • Console (like before only prettier)

  • CSV (comma-delimited text, suitable for import into spreadsheets)

  • JSON (suitable for machine parsing)

And 17 new checkers (as well as improved tests for some of the old):

  • binutils

  • bluez

  • bzip2

  • ffmpeg

  • gnutls

  • gstreamer

  • hostapd

  • libcurl

  • libdb

  • ncurses

  • nginx

  • openssh

  • python

  • rsyslog

  • strongswan

  • syslogng

  • varnish

Thanks to our many new and returning contributors for this 1.0 release. We have 21 new contributors since I last thanked people in 0.3.0:

  • @abhaykatheria

  • @ableabhinav

  • @AkechiShiro

  • @ananthan-123

  • @bigbird555

  • @brainwane

  • @FReeshabh

  • @hur

  • @k-udupa2000

  • @mariuszskon

  • @Niraj-Kamdar

  • @nitishsaini706

  • @oh6hay

  • @param211

  • @Purvanshsingh

  • @SaurabhK122

  • @sbs2001

  • @shreyamalviya

  • @SinghHrmn

  • @svnv

  • @utkarsh261

And I’d like to make a quick list of our previous contributors, some of whom have continued to be active for this release:

  • @bksahu

  • @CaptainDaVinci

  • @GiridharPrasath

  • @pdxjohnny

  • @PrajwalM2212

  • @rossburton

  • @sanketsaurav

  • @sannanansari

  • @terriko

  • @wzao1515

Thanks also to the many people who reported bugs and helped us make things better!

I want to particularly thank all those involved with Google Summer of Code – not only have you made our code better, but you’ve also helped us improve our onboarding process and just brought a huge amount of energy to this project in 2020.

CVE Binary Tool 0.3.1

Release Date: 27 Nov 2019

This release contains fixes so the CVE Binary Tool handles the new CVSS 3.1 data correctly.

You may also notice some new checkers thanks to our Hacktoberfest participants! We’re still working on more robust tests before they’re fully supported, but we figured it was more fun to give you the preview than specifically withhold them. Have fun, and please file bugs if anything doesn’t work for you so we know how to best to target our testing.

CVE Binary Tool 0.3.0

Release date: 13 Aug 2019

The 0.3.0 release adds Windows support to the cve-bin-tool, with many thanks to @wzao1515 who has been doing amazing work as our Google Summer of Code Student!

New checkers in this release:

  • icu

  • kerberos

  • libgcrypt

  • libjpeg

  • sqlite

  • systemd

New flags:

  • -s / –skip

    • allows you to disable a list of checkers

  • -m / –multithread

    • lets the scanner run in multithreaded mode for improved performance

  • -u / –update

    • allows you to choose if the CVE information is updated. Default is daily.

This release also contains a number of bugfixes and improved signatures.

Many thanks to our new contributors in this release: @wzao1515 @PrajwalM2212 @rossburton @GiridharPrasath @sannanansari @sanketsaurav @bksahu @CaptainDaVinci As well as the many people who reported bugs and helped us make things better!

CVE Binary Tool 0.2.0

Initial release, 18 Jan 2019.

CVE Binary Tool Contributor Guide

The CVE Binary Tool team participates in a few events every year that are aimed at new people in open source. This guide is meant to help people get over the initial hurdle of figuring out how to use git and make a contribution.

If you’ve already contributed to other open source projects, contributing to the CVE Binary Tool project should be pretty similar and you can probably figure it out by guessing. Experienced contributors might want to just skip ahead to the checklist for a great pull request But if you’ve never contributed to anything before, or you just want to see what we consider best practice before you start, this is the guide for you!

Imposter syndrome disclaimer

We want your help. No really, we do.

There might be a little voice inside that tells you you’re not ready; that you need to do one more tutorial, or learn another framework, or write a few more blog posts before you can help with this project.

I assure you, that’s not the case.

This document contains some contribution guidelines and best practices, but if you don’t get it right the first time we’ll try to help you fix it.

The contribution guidelines outline the process that you’ll need to follow to get a patch merged. By making expectations and process explicit, we hope it will make it easier for you to contribute.

And you don’t just have to write code. You can help out by writing documentation, tests, or even by giving feedback about this work. (And yes, that includes giving feedback about the contribution guidelines.)

If have questions or want to chat, we have a gitter chat room where you can ask questions, or you can put them in GitHub issues too.

Thank you for contributing!

This section is adapted from this excellent document from @adriennefriend

Code of Conduct

CVE Binary Tool contributors are asked to adhere to the Python Community Code of Conduct. Please contact Terri if you have concerns or questions relating to this code of conduct.

Note: The Python Community Code of Conduct is a required part of our participation in Google Summer of Code as a sub-org with the Python Software Foundation.

Development Environment

Linux is the preferred operating system to use while contributing to CVE Binary Tool. If you’re using Windows, we recommend setting up Windows Subsystem for Linux.

Getting and maintaining a local copy of the source code

There are lots of different ways to use git, and it’s so easy to get into a messy state that there’s a comic about it. So… if you get stuck, remember, even experienced programmers sometimes just delete their trees and copy over the stuff they want manually.

If you’re planning to contribute, first you’ll want to get a local copy of the source code (also known as “cloning the repository”)

git clone git@github.com:intel/cve-bin-tool.git

Once you’ve got the copy, you can update it using

git pull

You’re also going to want to have your own “fork” of the repository on GitHub. To make a fork on GitHub, read the instructions at Fork a repo. A fork is a copy of the main repository that you control, and you’ll be using it to store and share your code with others. You only need to make the fork once.

Once you’ve set up your fork, you will find it useful to set up a git remote for pull requests:

git remote add myfork git@github.com:MYUSERNAME/cve-bin-tool.git

Replace MYUSERNAME with your own GitHub username.

Choosing a version of python

CVE Binary Tool supports any version of python that has ongoing security support. There can be a bit of lag before we enable a new release or fully disable an old one. If you don’t need multiple versions of python for a specific bug, we recommend starting with either the most recent version of python or the one before (e.g. the first or second thing on the “Active Python Releases” list).

Note that some of our linters (tools used to help with code quality) may not work on the oldest version of python. That’s the last one on the “Active Python Releases” list. So if you’re doing development on the oldest version of python, for best results you should switch to a newer version before you run linters on your code or do a git commit.

Setting up a virtualenv

This section isn’t required, but many contributors find it helpful, especially for running tests using different versions of python.

virtualenv is a tool for setting up virtual python environments. This allows you to have all the dependencies for cve-bin-tool set up in a single environment, or have different environments set up for testing using different versions of Python.

To install it:

pip install virtualenv

To make a new venv using python 3.11:

virtualenv -p python3.11 ~/Code/venv3.11

Each time you want to use a virtualenv, you “activate” it using the activate script:

source ~/Code/venv3.11/bin/activate

And when you’re done with the venv, you can deactivate it using the deactivate command.

While you’re in a venv, the python command will point to whatever version you specified when the venv was created, and pip command will install things only in that venv so you don’t have to worry about conflicts with other versions or system packages.

Installing dependencies

The packages you need to run CVE Binary Tool are listed in the requirements.txt file in the main cve-bin-tool directory. You can install all of them using the following pip command:

pip install -U -r requirements.txt

The -U in that line above will update you to the latest versions of packages as needed, which we recommend because people running security tools generally want to have all the latest updates if possible. The -r requirements.txt specifies the file with all the requirements.

We also have a recommended list of dependencies just for developers that include things like the flake8 linter. You probably want to install them too if you’re intending to be a developer.

pip install -r dev-requirements.txt

Running your local copy of CVE Binary Tool

One of the reasons we suggest virtualenv is that it makes it easier to do this section.

If you want to run a local copy of cve-bin-tool, the recommended way is to install it locally. From the cve-bin-tool main directory, run:

If not in a virtual environment

python3 -m pip install --user -e .

If in a virtual environment

python3 -m pip install -e .

Then you can type cve-bin-tool on the command line and it will do the right thing. This includes some special code intended to deal with adding new checkers to the list on the fly so things should work seamlessly for you while you’re building new contributions.

Help, my checkers aren’t loading

CVE Binary Tool uses the installed egg file to figure out which checkers are installed. If you run it directly without installing it (e.g. you try to use python -m cve_bin_tool.cli), it will usually work fine but you may occasionally find that checkers aren’t loading properly. Typically this happens with new checkers you are adding, but sometimes if you git pull it will cause a similar effect. If you get into this state, you can fix it by running the following command from the main cve-bin-tool directory:

python setup.py egg_info

We recommend that you switch to having a local install to avoid this problem in the future.

Run the following in the main cve-bin-tool directory:

If not in a virtual environment

pip install --user -e .

If in a virtual environment

pip install -e .

Running tests

The CVE Binary Tool has a set of tests that can be run using pytest command. Typically you want to run pytest in the cve-bin-tool directory to run the short test suite and make sure tests pass.

After running pytest, you may get several test failures relating to ModuleNotFound error. If you have run pip install -r dev-requirements.txt or equivalent and are sure you have the required modules installed, your issue may be related to Python’s module search path. You can run this command instead :

python -m pytest

This bypasses potential issues with your system’s PATH environment variable, potentially looking in the wrong directory for the dependencies.

There is a README file in the tests directory which contains more info about how to run specific tests, or how to run the longer tests.

We have done our best to make tests stable and ensure that they pass at all times, but occasionally tests may fail due to factors outside your control (common causes: internet connectivity, rate limiting by NVD or new vulnerability data changing our test expectations). If a test doesn’t pass, you should look at it to see if any changes you made caused the failure. If you’re not sure, submit your code as a pull request and mention the issue and someone will try to help you sort it out.

When you submit your code as a pull request, the whole test suite will be run on windows and linux using the versions of python we support, including longer tests. We don’t expect you to do all that yourself; usually trying for one version of python on whatever local OS you have is good enough and you can let GitHub Actions do the rest!

Running linters

CVE Binary Tool uses a few tools to improve code quality and readability:

  • isort sorts imports alphabetically and by type

  • black provides automatic style formatting. This will give you basic PEP8 compliance. (PEP8 is where the default python style guide is defined.)

  • flake8 provides additional code “linting” for more complex errors like unused imports.

  • pyupgrade helps us be forward compatible with new versions of python.

  • bandit is more of a static analysis tool than a linter and helps us find potential security flaws in the code.

  • gitlint helps ensure that the commit messages follow Conventional Commits.

  • mypy helps ensure type definitions are correct when provided.

  • interrogate checks your code base for missing docstrings.

We provide a dev-requirements.txt file which includes all the precise versions of tools as they’ll be used in GitHub Actions. You an install them all using pip:

pip install -r dev-requirements.txt

Using pre-commit to run linters automatically

We’ve provided a pre-commit hook (in .pre-commit.config.yaml) so if you want to run isort/Black locally before you commit, you can install the hook as follows from the main cve-bin-tool directory:

pre-commit install --hook-type pre-commit --hook-type commit-msg

Once this is installed, all of those commands will run automatically when you run git commit and it won’t let you commit until any issues are resolved. (You can also run them manually using pre-commit with no arguments.) This will only run on files staged for commit (e.g. things where you’ve already run git add). If you want to run on arbitrary files, see below:

Running isort by itself

To format the imports using isort, you run isort --profile black followed by the filename. You will have to add --profile black when calling isort to make it compatible with Black formatter. For formatting a particular file name filename.py.

isort --profile black filename.py

Alternatively, you can run isort recursively for all the files by adding . instead of filename

isort --profile black .

Running black by itself

To format the code, you run black followed by the filename you wish to reformat. For formatting a particular file name filename.py.

black filename.py

In many cases, it will make your life easier if you only run black on files you’ve changed because you won’t have to scroll through a pile of auto-formatting changes to find your own modifications. However, you can also specify a whole folder using ./

Running bandit by itself

We have a configuration file for bandit called bandit.conf that you should use. This disables a few of the checkers.

To run it on all the code we scan, use the following:

bandit -c bandit.conf -r cve_bin_tool/ test/

You can also run it on individual files:

bandit -c bandit.conf filename.py

If you run it without the config file, it will run a few extra checkers, so you’ll get additional warnings.

Bandit helps you target manual code review, but bandit issues aren’t always things that need to be fixed, just reviewed. If you have a bandit finding that doesn’t actually need a fix, you can mark it as reviewed using a # nosec comment. If possible, include details as to why the bandit results are ok for future reviewers. For example, we have comments like #nosec uses static https url above in cases where bandit prompted us to review the variable being passed to urlopen().

Running mypy by itself

To check for static type checking, you run mypy followed by the filename you wish to check static type for. mypy checks the type annotations you provide and reports any type mismatches or missing annotations. For static type checking for a particular file name filename.py

mypy filename.py

Alternatively, you can run mypy on directory as well. For static type checking for a directory

mypy cve_bin_tool/

for someone who is new or are not familiar to python typing here are few resource - mypy documentation, resource for more understanding and its Quick reference and Python typing documentation

Running interrogate by itself

interrogate is a tool designed to enhance code documentation by identifying missing docstrings within your Python codebase. interrogate will tell you which methods, functions, classes, and modules have docstrings, and which do not.

When running interrogate, you need to specify the path to the directory or files that you want to check for missing docstrings.

interrogate [PATH]

In pre-commit, we use the following flags:

  • -vv makes interrogate print a report with all relevant functions showing which ones have or are missing docstrings

  • -i and -I ignore init functions and init.py files (because writing “initializes $class” repeatedly is boring)

  • The flags -M, -n, -c and -p exclude other types of functions. These are intended to reduce the scope of the problem and help us focus on filling in the most important docstrings first.

  • The -e flag in interrogate is used to exclude specific files or directories from analysis.

  • The -f flag in interrogate is employed to specify a minimum coverage percentage, and the tool will result in failure if the actual coverage falls below this designated threshold.

To run exactly what you’ll get when pre-commit runs, you can use the following:

interrogate -vv -i -I -M -C -n -p -f 60.0 -e fuzz/ -e test/ -e cve_bin_tool/checkers/ -e build/

You can specify a file or directory if you just want to check the files you changed.

Interrogate shows some report examples in their docs or you can look at the current cve-bin-tool reports in our linter runs on GitHub Actions

Other linting tools

As well as black for automatically making sure code adheres to the style guide, we use flake8 to help us find things like unused imports. The flake8 documentation covers what you need to know about running it.

We use pyupgrade to make sure our syntax is updated to fit new versions of python.

We also have a spell checker set up to help us avoid typos in documentation. The spelling actions readme file gives more information including how to add new words to the dictionary if needed.

We also have a tool to help make sure that new checkers are added to the tables in our documentation and relevant words associated with checker names are put in allow dictionary for spelling checks, this is done automatically with GitHub actions. The format_checkers code is here, if you’re curious.

You can view all the config files for GitHub Actions (what we use for Continuous Integration (CI)) in the .github/workflows directory.

Making a new branch & pull request

Git allows you to have “branches” with variant versions of the code. You can see what’s available using git branch and switch to one using git checkout branch_name.

To make your life easier, we recommend that the main branch always be kept in sync with the repo at https://github.com/intel/cve-bin-tool, as in you never check in any code to that branch. That way, you can use that “clean” main branch as a basis for each new branch you start as follows:

git checkout main
git pull
git checkout -b my_new_branch

Note: If you accidentally check something in to main and want to reset it to match our main branch, you can save your work using checkout -b and then do a git reset to fix it:

git checkout -b saved_branch
git reset --hard origin/main

You do not need to do the checkout step if you don’t want to save the changes you made.

When you’re ready to share that branch to make a pull request, make sure you’ve checked in all the files you’re working on. You can get a list of the files you modified using git status and see what modifications you made using git diff

Use git add FILENAME to add the files you want to put in your pull request, and use git commit to check them in. Try to use a clear commit message and use the Conventional Commits format.

Commit message tips

We usually merge pull requests into a single commit when we accept them, so it’s fine if you have lots of commits in your branch while you figure stuff out, and we can fix your commit message as needed then. But if you make sure that at least the title of your pull request follows the Conventional Commits format that you’d like for that merged commit message, that makes our job easier!

GitHub also has some keywords that help us link issues and then close them automatically when code is merged. The most common one you’ll see us use looks like fixes: #123456. You can put this in the title of your PR (what usually becomes the commit message when we merge your code), another line in the commit message, or any comment in the pull request to make it work. You and read more about linking a pull request to an issue in the GitHub documentation.

Sharing your code with us

Once your branch is ready and you’ve checked in all your code, push it to your fork:

git push myfork

From there, you can go to our pull request page to make a new pull request from the web interface.

Checklist for a great pull request

Here’s a quick checklist to help you make sure your pull request is ready to go:

  1. Have I run the tests locally on at least one version of Python?

    • Run the command pytest (See also Running Tests)

    • GitHub Actions will run the tests for you, but you can often find and fix issues faster if you do a local run of the tests.

  2. Have I run the code linters and fixed any issues they found?

    • We recommend setting up pre-commit so these are run automatically (See also Running Linters)

    • GitHub Actions will run the linters for you too if you forget! (And don’t worry, even experienced folk forget sometimes.)

    • You will be responsible for fixing any issue found by the linters before your code can be merged.

  3. Have I added any tests I need to prove that my code works?

    • This is especially important for new features or new checkers.

  4. Have I added or updated any documentation if I changed or added a feature?

  5. Have I used Conventional Commits to format the title of my pull request?

  6. If I closed a bug, have I linked it using one of GitHub’s keywords? (e.g. include the text fixed #1234)

  7. Have I checked on the results from GitHub Actions?

    • GitHub Actions will run all the tests, linters and a spell check for you. If you can, try to make sure everything is running cleanly with no errors before leaving it for a human code reviewer!

    • As of this writing, tests take less than 20 minutes to run once they start, but they can be queued for a while before they start. Go get a cup of tea or work on something else while you wait!

Code Review

Once you have created a pull request (PR), GitHub Actions will try to run all the tests on your code. If you can, make any modifications you need to make to ensure that they all pass, but if you get stuck a reviewer will see if they can help you fix them. Remember that you can run the tests locally while you’re debugging; you don’t have to wait for GitHub to run the tests (see the Running tests section above for how to run tests).

Someone will review your code and try to provide feedback in the comments on GitHub. Usually it takes a few days, sometimes up to a week. The core contributors for this project work on it as part of their day jobs and are usually on US Pacific time, so you might get an answer a bit faster during their work week.

If something needs fixing or we have questions, we’ll work back and forth with you to get that sorted. We usually do most of the chatting directly in the pull request comments on GitHub, but if you’re stuck you can also stop by our Gitter chat room to talk with folk outside of the bug.

Another useful tool is git rebase, which allows you to change the “base” that your code uses. We most often use it as git rebase origin/main which can be useful if a change in the main tree is affecting your code’s ability to merge. Rebasing is a bit much for an intro document, but there’s a git rebase tutorial here that you may find useful if it comes up.

Once any issues are resolved, we’ll merge your code. Yay!

In rare cases, the code won’t work for us and we’ll let you know. Sometimes this happens because someone else has already submitted a fix for the same bug, (Issues marked good first issue can be in high demand!) or because you worked on a checker that didn’t have a good signature. Don’t worry, these things happens, no one thinks less of you for trying!

Style Guide for cve-bin-tool

Most of our “style” stuff is caught by the black and flake8 linters, but we also recommend that contributors use f-strings for formatted strings:

String Formatting

Python provides many different ways to format the string (you can read about them here) and we use f-string formatting in our tool.

Note: f-strings are only supported in python 3.6+.

  • Example: Formatting string using f-string

#Program prints a string containing name and age of person
name = "John Doe"
age = 23
print(f"Name of the person is {name} and his age is {age}")

#Output
# "Name of the person is John Doe and his age is 23"

Note that the string started with the f followed by the string. Values are always added in the curly braces. Also we don’t need to convert age into string. (we may have used str(age) before using it in the string) f-strings are useful as they provide many cool features. You can read more about features and the good practices to use f-strings here.

Making documentation

The documentation for CVE Binary Tool can be found in the doc/ directory (with the exception of the README.md file, which is stored in the main directory but linked in the documentation directory for convenience).

Like many other Python-based projects, CVE Binary Tool uses Sphinx and ReadTheDocs to format and display documentation. If you’re doing more than minor typo fixes, you may want to install the relevant tools to build the docs. There’s a requirements.txt file available in the doc/ directory you can use to install sphinx and related tools:

cd doc/
pip install -r requirements.txt

Once those are installed, you can build the documentation using make in the docs directory:

make docs

or use sphinx-build directly with the following options:

sphinx-build -b html . _build

That will build the HTML rendering of the documentation and store it in the _build directory. You can then use your web browser to go to that directory and see what it looks like.

Note that you don’t need to commit anything in the _build directory. Only the .md and .rst files should be checked in to the repository.

If you don’t already have an editor that understands Markdown (.md) and RestructuredText (.rst) files, you may want to try out Visual Studio Code, which is free and has a nice Markdown editor with a preview.

Where should I start?

Many beginners get stuck trying to figure out how to start. You’re not alone!

Here’s three things we recommend:

  1. Try something marked as a “good first issue” We try to mark issues that might be easier for beginners.

  2. Add tests to an existing checker. This will give you some practice with the test suite.

  3. Add a new checker This will give you some deeper understanding of how the tool works and what a signature looks like. We have a few new checker requests listed in the “good first issue” list, or any linux library that has known CVEs (preferably recent ones) is probably interesting enough.

  4. Suggest fixes for documentation. If you try some instruction and it doesn’t work, or you notice a typo, those are always easy first commits! One place we’re a bit weak is instructions for Windows users.

If you get stuck or find something that you think should work but doesn’t, ask for help in an issue or stop by the cve-bin-tool gitter to ask questions.

Note that our “good first issue” bugs are in high demand during the February-April due to the start of Google Summer of Code. It’s totally fine to comment on a bug and say you’re interested in working on it, but if you don’t actually have any pull request with a tentative fix up within a week or so, someone else may pick it up and finish it. If you want to spend more time thinking, the new checkers (especially ones no one has asked for) might be a good place for a relaxed first commit.

Claiming an issue

  • You do not need to have an issue assigned to you before you work on it. To “claim” an issue either make a linked pull request or comment on the issue saying you’ll be working on it.

  • If someone else has already commented or opened a pull request, assume it is claimed and find another issue to work on.

  • If it’s been more than 1 week without progress, you can ask in a comment if the claimant is still working on it before claiming it yourself (give them at least 3 days to respond before assuming they have moved on).

The reason we do it this way is to free up time for our maintainers to do more code review rather than having them handling bug assignment. This is especially important to help us function during busy times of year when we take in a large number of new contributors such as Hacktoberfest (October) and the beginning of Google Summer of Code (January-April).

Adding a new checker to the cve-bin-tool

Requirements

In order to add a new checker to the CVE-bin-tool, one must provide a checker file. See any checker in the checkers/ directory as an example.

Currently, a checker must provide one class which inherits Checker class of the checkers module. class name of the checker must be same as filename of the checker with Checker suffix at the end. Ex: if you are creating a checker for curl binary then filename of checker should be curl.py and class definition should be:

from cve_bin_tool.checkers import Checker

class CurlChecker(Checker):

Every checker may contain following 5 class attributes specific to product(ex: curl) you are making checker for:

  1. CONTAINS_PATTERNS - list of commonly found strings in the binary of the product

  2. FILENAME_PATTERNS - list of different filename for the product

  3. VERSION_PATTERNS - list of version patterns found in binary of the product.

  4. VENDOR_PRODUCT - list of vendor product pairs for the product as they appear in NVD.

  5. IGNORE_PATTERNS (optional) - list of patterns that could cause false positives (e.g. error messages that mention specific product/versions)

CONTAINS_PATTERN, FILENAME_PATTERNS and VERSION_PATTERNS supports regex to cover wide range of use cases.

Once the checker is added, its name should also be added to __init__.py (so that from modules import * will find it).

Hints for finding the right data to use

Finding binary files to use

You can use any binary freely available on the Internet to build your checker. We typically build checkers for open source libraries because there is good data available for those; if building a checker for something that is not open source please be aware of licensing restrictions. Most people start this process with a binary they already want to detect, but sometimes folk see a request for a checker and might need to find the software first.

Typical places to get binaries:

  • Searching the project website for pre-compiled release files

  • Packages done up for Linux distributions such as Fedora, Debian, and OpenSUSE

  • Packages prepared for other operating systems

Here’s a worked example for Mozilla Firefox:

For Mozilla Firefox, I would start with Linux distributions that have pre-packaged versions, because I know they exist and that people will likely want to detect these particular packages if they’re scanning full systems. (You can do some research with a search engine if you don’t happen to know the software being requested.) You can find Linux packages using a search engine or by checking their websites, but as it happens the folk writing existing tests have left you some hints:

Each test we have includes the link where the test writer got the binary they used, so there’s a big list here in each file:

In general, the most recently updated tests are going to have the links that are easiest to work with – it’s the norm for software packages to be replaced with newer versions (e.g. to address security vulnerabilities!) and sometimes projects just rearrange their websites (although honestly, not that often). We store local copies of test data so we don’t have to update these all the time, but that means that some of those old URIs may just not work, so it’s best to choose a file that’s been updated relatively recently so you don’t get sent down a rabbit hole of “where the files used to be.”

To give you a worked example for this checker, let’s look at the most recently merged test data for the file checker:

You can see that the author gave us a pile of different tests from different locations:

  • http://rpmfind.net/ has a bunch of different Linux distributions represented. These particular ones point at OpenSUSE packages

  • http://ftp.fr.debian.org/ is a French Debian mirror.

  • https://downloads.openwrt.org/ is software included as part of openWRT (a distro targeted at embedded devices) (I know these off the top of my head, but if you don’t you can definitely search or go the main page of each site to help figure it out)

It’s probably not common to have Firefox on an embedded device, but both OpenSUSE and Debian should have versions, so let’s look at those two:

Look at the Debian link again:

It looks like they sort their packages alphabetically, and the last bit referred to the file package we were looking for in the test. What happens if you go up a level either using the ../ link provided at the top of that page, or just by truncating the URI?

How convenient, that gives you the list of packages that start with f. You should be able to find Firefox in there. Incidentally, if you happen to do more research, there’s also a Debian package search engine. But often just walking the directory tree on the mirrors is faster.

https://www.rpmfind.net/ is even easier to use: if you got to their main page, they have a package search box, so you can type in “Firefox” and get a huge list of packages:

https://www.rpmfind.net/linux/rpm2html/search.php?query=firefox&submit=Search+…

That should give you a couple of different binary versions of Firefox to run through the helper script program and use for the required tests. If you ever get stuck on this step, you can always ask for help in the issue tracker.

Finding a version pattern

The VERSION_PATTERNS contains strings which will be used as a signature for determining the version of the product that is present in the system. You should keep in mind that these strings should be consistent across all versions of the binary and in as many software distributions as possible.

You can get a basic idea of the pattern from looking at the project’s documentation/website or use cvedetails since it catalogs vulnerable versions and thus has version lists. Once you know what the version numbers look like, you’ll need to find them in the code or the binary itself to make sure you’ve got a findable pattern.

A few ways to do it:

  • The CVE Binary tool basically works by running the command line utility strings on a file, so if you have a local copy of the library, you can run strings $libraryname and see what comes out. try strings $libraryname | grep $version and see what you find, and if you don’t find it that way strings $libraryname | less and page through (maybe run a filter in there so it’s only strings over a certain size?)

  • If you don’t have a copy, browse through the source to find the version string. It’s usually helpfully named something like ‘version’ so a quick grep/search often will turn it up, and if you know the latest version number (usually proudly mentioned in the latest news post or similar) you can grep for that and then look at the history to see what valid patterns look like.

Multi-line version patterns

In Windows, a new line is denoted using “\r\n” and in Linux it’s “\n”.

For example, if the version string looks like this:

  <artifactId>commons-compress</artifactId>
  <version>1.16.1</version>

Then a good regex signature for this will be r"<artifactId>commons-compress</artifactId>\r?\n  <version>([0-9]+\.[0-9]+(\.[0-9]+)?)</version>". And in case of the mapping tests, the version_strings parameter doesn’t support regex strings, so just use “\r\n” to indicate a new line.

Avoiding false positives (beware the X.X.X version pattern!)

It can be very tempting to have a version pattern that matches X.X.X where X is a number (or in regex form: r"[0-9]+\.[0-9]+\.[0-9]+"). But beware! There are lots of other libraries potentially compiled in to your binary that will match X.X.X. The ones you’re most likely going to see are gcc and glibc, the standard c library.

For an example, here’s a list of some of the “interesting” version-like strings from one of our binary test files:

~/Code/cve-bin-tool$ strings test/assets/test-curl-7.34.0.out
This program is designed to test the cve-bin-tool checker.
It outputs a few strings normally associated with libcurl 7.34.0.
They appear below this line.
------------------
An unknown option was passed in to libcurl
CLIENT libcurl 7.34.0
GCC: (x86_64, Built by MinGW-W64 project) 8.1.0

As you can see, there’s a lot of things that will match X.X.X:

  • libcurl is version 7.34.0

  • gcc is version 8.1.0

So you want something that makes the version string a little more precise to the product you’re looking for. For example, if we were intentionally looking for libcurl (as in, writing a libcurl checker), we could use the string curl or libcurl as a prefix and get a regex that would tell us about libcurl without also telling us the GCC version.

So a good regex signature for libcurl might be r"curl[ -/]([678]+\.[0-9]+\.[0-9]+)"

The whole point of the CVE Binary Tool is to detect libraries that you might not know are there, so we’d expect it often to be used on binaries that have a lot of libraries compiled into them. Finding a regex that detects only what you care about even in the face of a lot of similar strings is essential for us to avoid false positives.

It’s also worth noting that sometimes there just aren’t great version strings available: sometimes X.X.X is all you can find. If you get stuck at this point, please make a note of it in the New Checker issue if there is one. (You can make a new one and note it there if there isn’t.) That helps other contributors know that that particular checker is going to be hard to do. Once you’ve done that, you can abandon the checker and find something easier to work on, or you can try to think outside the box to find another way to detect the version. One example is how we did it for the sqlite3 get_version_map() function where the checker uses version hashes from the website that are also stored as strings in the binary.

Finding FILENAME_PATTERNS

The FILENAME_PATTERNS contains the names of the files in the binary where the above signatures were found. If there are more than one place where the version strings are found, please make sure that you add all the filenames.

Choosing contains patterns to detect the library

contains patterns are the string pattern that you commonly found in the binary of the product you are looking for. You want a signature that hasn’t changed in a large number of versions so you’ll detect the library as long as possible (and if you notice that it did change before some version date, you can always add more strings to improve the coverage). If you have a copy of the library you can run strings $libraryname to find some candidate strings that look good, then you should look at their source repository to see when those strings were added and if they were changed. (there’s a ‘history’ button on github for this, or other tools for other repositories). CONTAINS_PATTERNS field supports regex pattern so you can use creative signature which remain same for number of versions.

Note: We by default include VERSION_PATTERNS as a valid CONTAINS_PATTERNS

You can find these by-

strings (path of the binary) | grep -i (product_name)

Quickstart for finding patterns

What often helps is trying to find an .rpm (or more than one) or a package which contains the product you’re looking for.

Searching on https://pkgs.org is a good place to start.

For this example we’ll be using libvorbis: https://pkgs.org/search/?q=libvorbis

In the below example we picked fedora 33’s package for version 1.3.7 of libvorbis. We can extract the .rpm file using a combination of rpm2cpio and cpio or using rpmfile. Sometimes you’ll have packages which come in .deb or .tar files.

  • .deb files can be extracted with ar x somefile.deb && tar xvf data.tar.xz

  • .tar files can be extracted using tar

$ curl -sfL 'https://download-ib01.fedoraproject.org/pub/fedora/linux/releases/33/Everything/x86_64/os/Packages/l/libvorbis-1.3.7-2.fc33.x86_64.rpm' | rpmfile -xv -
/tmp/tmp.U3wkntEqtD/usr/lib/.build-id/02/980384bc359497f0121fc74974e465ba7e29aa
/tmp/tmp.U3wkntEqtD/usr/lib/.build-id/1c/ff0ed918467a6224a5108793bf779e61486151
/tmp/tmp.U3wkntEqtD/usr/lib/.build-id/75/8407ea857c63ae42c4d9959ad252de6fb9bcca
/tmp/tmp.U3wkntEqtD/usr/lib64/libvorbis.so.0
/tmp/tmp.U3wkntEqtD/usr/lib64/libvorbis.so.0.4.9
/tmp/tmp.U3wkntEqtD/usr/lib64/libvorbisenc.so.2
/tmp/tmp.U3wkntEqtD/usr/lib64/libvorbisenc.so.2.0.12
/tmp/tmp.U3wkntEqtD/usr/lib64/libvorbisfile.so.3
/tmp/tmp.U3wkntEqtD/usr/lib64/libvorbisfile.so.3.3.8
/tmp/tmp.U3wkntEqtD/usr/share/doc/libvorbis/AUTHORS
/tmp/tmp.U3wkntEqtD/usr/share/licenses/libvorbis/COPYING

Then look for which files you downloaded are binaries or libraries. We can use the file command combined with the find command for this. The find command will list every file in the directory we provide to it (. in this case) and execute any program we want using that filename. In this case we want to run the file command on each file we get from find.

We want to filter the output using grep to show us only executables (programs you run) and shared objects (libraries programs use) using -E 'executable,|shared object,' which is a regex which says to show lines that find output if they have either executable, or shared object, in them.

The final tee command in combination with sed is creating a new file called executables.txt which has all the filenames in it. It does this by only writing what comes before the : to the file that was in the output of the grep command which looked for executables.

$ find . -exec file {} \; | grep -E 'executable,|shared object,' | tee >(sed -e 's/:.*//g' > executables.txt)
./usr/lib64/libvorbisfile.so.3.3.8: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=1cff0ed918467a6224a5108793bf779e61486151, stripped
./usr/lib64/libvorbisenc.so.2.0.12: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=02980384bc359497f0121fc74974e465ba7e29aa, stripped
./usr/lib64/libvorbis.so.0.4.9: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=758407ea857c63ae42c4d9959ad252de6fb9bcca, stripped

You’ll want to run strings on those binaries and do a case insensitive search for the package name using grep -i.

$ strings $(cat executables.txt) | sort | uniq | grep -i libvorbis
3?Xiph.Org libVorbis 1.3.7
libvorbisenc.so.2
libvorbisenc.so.2.0.12-1.3.7-2.fc33.x86_64.debug
libvorbisfile.so.3
libvorbisfile.so.3.3.8-1.3.7-2.fc33.x86_64.debug
libvorbis.so.0
libvorbis.so.0.4.9-1.3.7-2.fc33.x86_64.debug
Xiph.Org libVorbis I 20200704 (Reducing Environment)

You also might want to look for the version number. In this case it’s 1.3.7.

$ strings $(cat executables.txt) | sort | uniq | grep -i 1.3.7
3?Xiph.Org libVorbis 1.3.7
libvorbisenc.so.2.0.12-1.3.7-2.fc33.x86_64.debug
libvorbisfile.so.3.3.8-1.3.7-2.fc33.x86_64.debug
libvorbis.so.0.4.9-1.3.7-2.fc33.x86_64.debug

In this case the most interesting line in the output of the above two commands is 3?Xiph.Org libVorbis 1.3.7. We can probably use this to create a regex for VERSION_PATTERNS.

That regex might look like this: 3\?Xiph.Org libVorbis ([0-9]+\.[0-9]+\.[0-9]+)

If you can’t get a signature match using just regex you may end up needing to overwrite the get_version() method for the checker, but that should be a last resort if you can’t find a regex that works for VERSION_PATTERNS.

A note about this example: In the case of libvorbis the versions containing CVEs are 1.2.0 and below. The .rpm we used for this example was from version 1.3.7. While this was a nice example for how one might find a signature, it in the end is not all the work that is needed to create a checker for libvorbis. We need to make sure that any checker we develop has a get_version() function which works for versions of the software which have CVEs. If not overridden in a subclass the Checker base class implements a get_version() method which will use regex to determine the version (as described above). In the case of libvorbis a custom get_version() function is likely needed, this is because the signature we found is not in the 1.2.0 version, where the CVE is found.

Finding Vendor Product pairs

Every checker class must contain the vendor and product name pair(s) as they appear in NVD. The best way to do this is to search the cached sqlite database of the NVD using a CVE you want to know the vendor product pair(s) for.

$ sqlite3 ~/.cache/cve-bin-tool/cve.db \
    "SELECT vendor, product FROM cve_range WHERE CVE_Number='CVE-2016-0718';" \
    | sed -e 's/|/, /g' -e 's/^/VPkg\: /'
VPkg: apple, mac_os_x
VPkg: canonical, ubuntu_linux
VPkg: debian, debian_linux
VPkg: libexpat_project, libexpat
VPkg: mozilla, firefox
VPkg: opensuse, leap
VPkg: suse, linux_enterprise_debuginfo

VENDOR_PRODUCT attribute should have list of tuples of vendor product pair found in the listings. Some of the listings will be with regards to products that include this product. For our example all listings except libexpat_project, libexpat merely include the target product (libexpat for the example SQL query).

Helper-Script

Helper-Script is a tool that takes a package(i.e. busybox_1.30.1-4ubuntu9_amd64.deb) as input and returns:

  1. CONTAINS_PATTERNS - list of commonly found strings in the binary of the product

  2. FILENAME_PATTERNS - list of different filename for the product

  3. VERSION_PATTERNS - list of version patterns found in binary of the product.

  4. VENDOR_PRODUCT - list of vendor product pairs for the product as they appear in NVD.

Helper-Script can also take multiple packages and PRODUCT_NAME(required) as input and return common strings for CONTAINS_PATTERNS.

Usage: python -m cve_bin_tool.helper_script

positional arguments:
  filenames             files to scan

optional arguments:
  -h, --help            show this help message and exit
  -p PRODUCT_NAME, --product PRODUCT_NAME
                        provide product-name that would be searched
  -v VERSION_NUMBER, --version VERSION_NUMBER
                        provide version that would be searched
  -l {debug,info,warning,error,critical}, --log {debug,info,warning,error,critical}
                        log level (default: warning)
  --string-length STRING_LENGTH
                        changes the output string-length for CONTAINS_PATTERNS (default: 40)

Let us see the tool in action with an example with the already existing busybox checker:

First, we download some packages for Busybox, the directory looks something like this:

.
├── busybox-1.33.1-1.fc35.x86_64.rpm
└── busybox_1.30.1-4ubuntu9_amd64.deb

Now, we run the script. In this case, running the script for both windows and linux would result in something like this:

windows > python -m cve_bin_tool.helper_script busybox-1.33.1-1.fc35.x86_64.rpm --product busybox --version 1.33.1
linux $ python3 -m cve_bin_tool.helper_script busybox-1.33.1-1.fc35.x86_64.rpm --product busybox --version 1.33.1
────────────────────────────────────────────────────────── BusyboxChecker ───────────────────────────────────────────────────────────

# Copyright (C) 2021 Intel Corporation
# SPDX-License-Identifier: GPL-3.0-or-later


"""
CVE checker for busybox:

<provide reference links here>
"""
from cve_bin_tool.checkers import Checker


class BusyboxChecker(Checker):
        CONTAINS_PATTERNS = [
                r"BusyBox is a multi-call binary that combines many common Unix",
                r"BusyBox is copyrighted by many authors between 1998-2015.",
                r"BusyBox v1.33.1 (2021-05-06 17:29:07 UTC)",
                r"crond (busybox 1.33.1) started, log level %d",
                r"link to busybox for each function they wish to use and BusyBox",
        ]
        FILENAME_PATTERNS = [
                r"busybox", <--- this is a really common filename pattern
        ]
        VERSION_PATTERNS = [
                r"BusyBox v1.33.1 (2021-05-06 17:29:07 UTC)",
                r"crond (busybox 1.33.1) started, log level %d",
                r"SERVER_SOFTWARE=busybox httpd/1.33.1",
                r"syslogd started: BusyBox v1.33.1",
                r"tar (busybox) 1.33.1",
                r"fsck (busybox 1.33.1)",
        ]
        VENDOR_PRODUCT = [('busybox', 'busybox'), ('rob_landley', 'busybox')]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Try this against a few more busybox packages across different distros and see which strings are common among the following. Then follow the above steps to create the checker.

To get common strings for CONTAINS_PATTERNS in multiple busybox packages, we can use the script like this:

windows > python3 -m cve_bin_tool.helper_script busybox_1.30.1-4ubuntu6_amd64.deb busybox-1.33.0-3.fc34.x86_64.rpm --product busybox
linux $ python3 -m cve_bin_tool.helper_script busybox_1.30.1-4ubuntu6_amd64.deb busybox-1.33.0-3.fc34.x86_64.rpm --product busybox
─────────────────────────────────────────────────────── Common CONTAINS_PATTERNS strings for BusyboxChecker──────────────────────────

class BusyboxChecker(Checker):
 CONTAINS_PATTERNS = [
                r"BusyBox is a multi-call binary that combines many common Unix",
                r"BusyBox is copyrighted by many authors between 1998-2015.",
                r"link to busybox for each function they wish to use and BusyBox",
 ]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

NOTE: If you look at our existing checkers, you’ll see that some strings are commented out in CONTAINS_PATTERNS. These strings are kept there as potential strings in case if the currently used strings stop working in the future versions. If you also find more than 2-3 strings, it’s recommended to comment them out for future reference.

Currently, if you receive multiple vendor-product pairs, select the appropriate vendor-product pair from the following pairs obtained manually. In this case, it is [('busybox', 'busybox')].

Since VERSION_PATTERNS returned by Helper-Script gives us a lists of some of the possible candidates for version strings. So, form the required regular expression by selecting the appropriate version string candidate. A good place to start would be to use python’s in-built re module or alternatively you could use pythex.org - which let’s you check if a given regex works the way you intend it to work. In this case, the obtained regex pattern is "BusyBox v([0-9]+\.[0-9]+\.[0-9]+)".

Adding tests

There are two types of tests you want to add to prove that your checker works as expected:

  1. Test to show that the cve mapping works as expected.

  2. Tests to show that the checker correctly detects real binaries.

You can read about how to add these in tests/README.md

Running tests

To run the tests for cve-bin-tool

pytest

To run tests for a particular checker

pytest -k $checkername

Alternatively you can run Long Tests using

LONG_TESTS=1 pytest -k $checkername

You can run tests in parallel by using

pytest -n 4

This will spawn 4 worker processes to leverage multicore system.
You can set an arbitrary number of workers. A good rule of thumb is to specify no. of workers equal to no. of cores.

How it works

The CVE-bin-checker works by extracting strings from binaries and determining if a given library has been compiled into the binary. For this, Checker class contains two methods: 1) guess_contains() and 2) get_version().

  1. guess_contains() method takes list of extracted string lines as an input and return True if it finds any of the CONTAINS_PATTERNS on any line from the lines.

  2. get_version() method takes list of extracted string lines and the filename as inputs and returns information about whether the binary contains the library in question, is a copy of the library in question, and if either of those are true it also returns a version string. If the binary does not contain the library, this function returns an empty dictionary.

If curl product is being scanned, get_version() method of CurlChecker will return following dictionary.

{
  "is_or_contains": "is",
  "modulename": "curl",
  "version": "6.41.0"
}

In most of the cases, Just providing above five class attributes will be enough. But sometimes, you need to override this method to correctly detect version of the product. We have done this in the checkers of python andsqlite.

Updating checker table

You do not need to run format_checkers.py to update the checker table in documentation. A pull request with updated checker table is created automatically when a new checker is merged.

Pull Request Template

When you are ready to share your code, you can go to our pull request page to make a new pull request from the web interface and to use the guided template for new checker, click on the Compare & pull request button and add ?template=new_checker.md at the end of the url.

SBOMs For Humans

Made possible with sbom2doc

These files are automatically generated as part of the docs/ build process for cve-bin-tool.readthedocs.io

To manually build human readable files:

  • install docs/requirements.txt

  • navigate to the sbom/ directory in your terminal and run make

Generated human readable SBOMs:

New Contribution Tips

This file contains the tips/links I put into bugs marked “good first issue” so that new contributors have the guidance they need right in the bug.

Short tips for new contributors:

  • cve-bin-tool’s contributor docs

  • If you’ve contributed to open source but not this project, you might just want our checklist for a great pull request

  • cve-bin-tool uses https://www.conventionalcommits.org/ style for commit messages, and we have a test that checks the title of your pull request (PR). A good potential title for this one is in the title of this issue.

  • You can make an issue auto close by including a comment “fixes #ISSUENUMBER” in your PR comments where ISSUENUMBER is the actual number of the issue. This “links” the issue to the pull request.

Claiming issues:

  • You do not need to have an issue assigned to you before you work on it. To “claim” an issue either make a linked pull request or comment on the issue saying you’ll be working on it.

  • If someone else has already commented or opened a pull request, assume it is claimed and find another issue to work on.

  • If it’s been more than 1 week without progress, you can ask in a comment if the claimant is still working on it before claiming it yourself (give them at least 3 days to respond before assuming they have moved on).

PyPi Downloads Stats Visualization

This python script pulls data cve-bin-tool download stats from BigQuery public data table and add geo based visualization.

There are two main components in this script

  • Get data from Google BigQuery public data set

  • Process and visualize the data using pandas, numpy, geopy and folium

In order to pull data from BigQuery, you need to have Google credential. The BigQuery free service has limitation of how many data you can query per day. Given that said, an alternative method to read data from json file is provided to visualize the data if your free quota is reached.

Two visualization maps are generated, one is mainly used to show number of downloads

Number of Downloads

The second one tries to use color to indicate the amount of downloads.

Number of Downloads

There are certain limitations in the visualization, for one, it is not easy to display total number of downloads when there is no child clusters.

Indices and tables