Skip to content

Commit

Permalink
Add pdf output (#1114) (#1115)
Browse files Browse the repository at this point in the history
  • Loading branch information
anthonyharrison committed Apr 15, 2021
1 parent c92b230 commit 10cb6fd
Show file tree
Hide file tree
Showing 6 changed files with 361 additions and 12 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)


The CVE Binary Tool scans for a number of common, vulnerable open source
components such as openssl, libpng, libxml2, and expat to let you know
if a given directory or binary file includes common libraries with
The CVE Binary Tool scans for a number of common, vulnerable open source
components such as openssl, libpng, libxml2, and expat to let you know
if a given directory or binary file includes common libraries with
known vulnerabilities., known as CVEs ([Common Vulnerabilities and Exposures](https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures#:~:text=Common%20Vulnerabilities%20and%20Exposures%20(CVE)%20is%20a%20dictionary%20of%20common,publicly%20known%20information%20security%20vulnerabilities.)).

See our [documentation](https://cve-bin-tool.readthedocs.io/en/latest/) and [quickstart guide](https://cve-bin-tool.readthedocs.io/en/latest/README.html)
Usage:
`cve-bin-tool <directory/file to scan> `

You can also do `python -m cve_bin_tool.cli`
which is useful if you're trying the latest code from
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](https://github.com/intel/cve-bin-tool).


Expand All @@ -31,7 +31,7 @@ which is useful if you're trying the latest code from
update schedule for NVD database (default: daily)
--disable-version-check
skips checking for a new version

Input:
directory directory to scan
-i INPUT_FILE, --input-file INPUT_FILE
Expand All @@ -47,7 +47,7 @@ which is useful if you're trying the latest code from
provide output filename (default: output to stdout)
--html-theme HTML_THEME
provide custom theme directory for HTML Report
-f {csv,json,console,html}, --format {csv,json,console,html}
-f {csv,json,console,html,pdf}, --format {csv,json,console,html,pdf}
update output format (default: console)
-c CVSS, --cvss CVSS minimum CVSS score (as integer in range 0 to 10) to
report (default: 0)
Expand All @@ -72,14 +72,14 @@ Note that you can use `-i` or `--input-file` option to produce list of CVEs foun

> Note: For backward compatibility, we still support `csv2cve` command for producing CVEs from csv but we recommend using new `--input-file` command instead.
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
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](https://github.com/intel/cve-bin-tool/blob/main/test/config/)

The 0.3.1 release is intended to be the last release to officially support
python 2.7; please switch to python 3.6+ for future releases and to use the
development tree. You can check [our CI configuration](https://github.com/intel/cve-bin-tool/blob/main/.github/workflows/pythonapp.yml) to see what versions of python we're explicitly testing.

If you want to integrate cve-bin-tool as a part of your github action pipeline.
If you want to integrate cve-bin-tool as a part of your github action pipeline.
You can checkout our example [github action](https://github.com/intel/cve-bin-tool/blob/main/doc/how_to_guides/cve_scanner_gh_action.yml).

This readme is intended to be a quickstart guide for using the tool. If you
Expand All @@ -93,7 +93,7 @@ match certain vulnerable versions of the following libraries and tools:
| | | | Available checkers | | | |
| -------- | --------- | ---------------| ------------------ | ---------- | ---------- | ------- |
| avahi | bash | bind | binutils | busybox | bzip2 | cups |
| curl | dovecot | expat | ffmpeg | freeradius | gcc | gimp |
| curl | dovecot | expat | ffmpeg | freeradius | gcc | gimp |
| gnutls | glibc | gstreamer | haproxy | hostapd | icecast | icu |
| irssi | kerberos | libarchive | libdb | libgcrypt | libjpeg | libnss |
| libtiff | libvirt | lighttpd | mariadb | memcached | ncurses | nessus |
Expand Down
2 changes: 1 addition & 1 deletion cve_bin_tool/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def main(argv=None):
"-f",
"--format",
action="store",
choices=["csv", "json", "console", "html"],
choices=["csv", "json", "console", "html", "pdf"],
help="update output format (default: console)",
)
output_group.add_argument(
Expand Down
11 changes: 11 additions & 0 deletions cve_bin_tool/cvedb.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ def __init__(
self.dbpath = os.path.join(self.cachedir, DBNAME)
self.connection = None
self.session = session
self.cve_count = -1

def get_cve_count(self):
if self.cve_count == -1:
# Force update
self.check_cve_entries()
return self.cve_count

def get_db_update_date(self):
return os.path.getmtime(self.dbpath)

async def getmeta(self, session, meta_url):
async with session.get(meta_url) as response:
Expand Down Expand Up @@ -281,6 +291,7 @@ def check_cve_entries(self):
cve_entries = cursor.fetchone()[0]
self.LOGGER.info(f"There are {cve_entries} CVE entries in the database")
self.db_close()
self.cve_count = cve_entries
return cve_entries > 0

def init_database(self):
Expand Down
73 changes: 72 additions & 1 deletion cve_bin_tool/output_engine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
from .console import output_console
from .html import output_html
from .util import add_extension_if_not, format_output, generate_filename
from . import pdfbuilder
from ..cvedb import CVEDB
from ..version import VERSION


def output_json(all_cve_data: Dict[ProductInfo, CVEData], outfile: IO):
Expand Down Expand Up @@ -42,6 +45,69 @@ def output_csv(all_cve_data: Dict[ProductInfo, CVEData], outfile):
writer.writerows(formatted_output)


def output_pdf(all_cve_data: Dict[ProductInfo, CVEData], outfile):
""" Output a PDF of CVEs """
cvedb_data = CVEDB()
db_date = time.strftime(
"%d %B %Y at %H:%M:%S", time.localtime(cvedb_data.get_db_update_date())
)
app_version = VERSION
# Build document
pdfdoc = pdfbuilder.PDFBuilder()
cm = pdfdoc.cm
severity_colour = {
"LOW": pdfdoc.blue,
"MEDIUM": pdfdoc.green,
"HIGH": pdfdoc.orange,
"CRITICAL": pdfdoc.red,
}
pdfdoc.front_page("Vulnerability Report")
pdfdoc.heading(1, "Introduction")
pdfdoc.paragraph(
"The identification of vulnerabilities has been performed using cve-bin-tool version "
+ app_version
)
pdfdoc.paragraph(
"The data used has been obtained from the NVD database which was retrieved on "
+ db_date
+ " and contained "
+ str(cvedb_data.get_cve_count())
+ " entries."
)
pdfdoc.heading(1, "List of Identified Vulnerabilities")
pdfdoc.paragraph(
"The following vulnerabilities are reported against the identified versions of the libraries."
)
pdfdoc.createtable(
"Vulnlist",
["Vendor", "Product", "Version", "CVE Number", "Severity"],
pdfdoc.tblStyle,
)
row = 1
for product_info, cve_data in all_cve_data.items():
for cve in cve_data["cves"]:
entry = [
product_info.vendor,
product_info.product,
product_info.version,
cve.cve_number,
cve.severity,
]
pdfdoc.addrow(
"Vulnlist",
entry,
[
("TEXTCOLOR", (3, row), (4, row), severity_colour[cve.severity]),
("FONT", (3, row), (4, row), "Helvetica-Bold"),
],
)
row += 1
pdfdoc.showtable("Vulnlist", widths=[3 * cm, 2 * cm, 2 * cm, 4 * cm, 3 * cm])
pdfdoc.pagebreak()
pdfdoc.paragraph("END OF DOCUMENT.")
pdfdoc.publish(outfile)


class OutputEngine:
def __init__(
self,
Expand Down Expand Up @@ -72,6 +138,8 @@ def output_cves(self, outfile, output_type="console"):
output_json(self.all_cve_data, outfile)
elif output_type == "csv":
output_csv(self.all_cve_data, outfile)
elif output_type == "pdf":
output_pdf(self.all_cve_data, outfile)
elif output_type == "html":
output_html(
self.all_cve_data,
Expand Down Expand Up @@ -129,5 +197,8 @@ def output_file(self, output_type="console"):
self.logger.info(f"Output stored at {self.filename}")

# call to output_cves
with open(self.filename, "w") as f:
mode = "w"
if output_type == "pdf":
mode = "wb"
with open(self.filename, mode) as f:
self.output_cves(f, output_type)
Loading

0 comments on commit 10cb6fd

Please sign in to comment.