Skip to content

Commit

Permalink
Merge branch 'main' into chore/c-autobuild-components
Browse files Browse the repository at this point in the history
  • Loading branch information
terriko authored Jul 13, 2023
2 parents b338645 + 0b9ce36 commit 80fd618
Show file tree
Hide file tree
Showing 14 changed files with 1,126 additions and 644 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@004c5de30b6423267685b897a3d595e944f7fed5 # v2.20.2
uses: github/codeql-action/init@46ed16ded91731b2df79a2893d3aea8e9f03b5c4 # v2.20.3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -76,4 +76,4 @@ jobs:
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@004c5de30b6423267685b897a3d595e944f7fed5 # v2.20.2
uses: github/codeql-action/analyze@46ed16ded91731b2df79a2893d3aea8e9f03b5c4 # v2.20.3
158 changes: 107 additions & 51 deletions cve_bin_tool/cvedb.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@
from rich.progress import track

from cve_bin_tool.async_utils import run_coroutine
from cve_bin_tool.data_sources import curl_source, gad_source, nvd_source, osv_source
from cve_bin_tool.data_sources import (
curl_source,
epss_source,
gad_source,
nvd_source,
osv_source,
)
from cve_bin_tool.error_handler import ERROR_CODES, CVEDBError, ErrorMode, SigningError
from cve_bin_tool.fetch_json_db import Fetch_JSON_DB
from cve_bin_tool.log import LOGGER
Expand Down Expand Up @@ -53,6 +59,60 @@ class CVEDB:
gad_source.GAD_Source,
]

INSERT_QUERIES = {
"insert_severity": """
INSERT or REPLACE INTO cve_severity(
CVE_number,
severity,
description,
score,
cvss_version,
cvss_vector,
data_source,
last_modified
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""",
"insert_cve_range": """
INSERT or REPLACE INTO cve_range(
cve_number,
vendor,
product,
version,
versionStartIncluding,
versionStartExcluding,
versionEndIncluding,
versionEndExcluding,
data_source
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
"insert_exploit": """
INSERT or REPLACE INTO cve_exploited (
cve_number,
product,
description
)
VALUES (?,?,?)
""",
"insert_cve_metrics": """
INSERT or REPLACE INTO cve_metrics (
cve_number,
metric_id,
metric_score,
metric_field
)
VALUES (?, ?, ?, ?)
""",
"insert_metrics": """
INSERT or REPLACE INTO metrics (
metrics_id,
metrics_name
)
VALUES (?, ?)
""",
}

def __init__(
self,
sources=None,
Expand Down Expand Up @@ -88,6 +148,8 @@ def __init__(
self.cve_count = -1
self.all_cve_entries: list[dict[str, Any]] | None = None

self.epss_data = None

self.exploits_list: list[Any] = []
self.exploit_count = 0

Expand Down Expand Up @@ -126,6 +188,8 @@ async def refresh(self) -> None:
if self.version_check:
check_latest_version()

epss = epss_source.Epss_Source()
self.epss_data = await epss.update_epss()
await self.get_data()

def refresh_cache_and_update_db(self) -> None:
Expand Down Expand Up @@ -269,7 +333,7 @@ def table_schemas(self):
versionEndIncluding TEXT,
versionEndExcluding TEXT,
data_source TEXT,
FOREIGN KEY(cve_number) REFERENCES cve_severity(cve_number)
FOREIGN KEY(cve_number, data_source) REFERENCES cve_severity(cve_number, data_source)
)
"""
exploit_table_create = """
Expand Down Expand Up @@ -306,44 +370,6 @@ def table_schemas(self):
metrics_table,
)

def insert_queries(self):
cve_severity = """
cve_severity(
CVE_number,
severity,
description,
score,
cvss_version,
cvss_vector,
data_source,
last_modified
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
"""
insert_severity = f"INSERT or REPLACE INTO {cve_severity}"
insert_cve_range = """
INSERT or REPLACE INTO cve_range(
cve_number,
vendor,
product,
version,
versionStartIncluding,
versionStartExcluding,
versionEndIncluding,
versionEndExcluding,
data_source
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
"""
insert_exploit = """
INSERT or REPLACE INTO cve_exploited (
cve_number,
product,
description
)
VALUES (?,?,?)
"""
return insert_severity, insert_cve_range, insert_exploit

def init_database(self) -> None:
"""Initialize db tables used for storing cve/version data"""

Expand Down Expand Up @@ -429,6 +455,9 @@ def populate_db(self) -> None:
we'll need a better parser to match those together.
"""

self.store_epss_data()
self.populate_metrics()

for idx, data in enumerate(self.data):
_, source_name = data

Expand All @@ -437,8 +466,8 @@ def populate_db(self) -> None:
break

for cve_data, source_name in self.data:
if source_name != "NVD" and cve_data[0] is not None:
cve_data = self.update_vendors(cve_data)
# if source_name != "NVD" and cve_data[0] is not None:
# cve_data = self.update_vendors(cve_data)

severity_data, affected_data = cve_data

Expand All @@ -457,8 +486,8 @@ def populate_db(self) -> None:
self.db_close()

def populate_severity(self, severity_data, cursor, data_source):
(insert_severity, _, _) = self.insert_queries()
del_cve_range = "DELETE from cve_range where CVE_number=?"
insert_severity = self.INSERT_QUERIES["insert_severity"]
del_cve_range = "DELETE from cve_range where CVE_number=? and data_source=?"

for cve in severity_data:
# Check no None values
Expand Down Expand Up @@ -497,10 +526,11 @@ def populate_severity(self, severity_data, cursor, data_source):
LOGGER.info(f"Unable to insert data for {data_source} - {e}\n{cve}")

# Delete any old range entries for this CVE_number
cursor.executemany(del_cve_range, [(cve["ID"],) for cve in severity_data])
for cve in severity_data:
cursor.execute(del_cve_range, [cve["ID"], data_source])

def populate_affected(self, affected_data, cursor, data_source):
(_, insert_cve_range, _) = self.insert_queries()
insert_cve_range = self.INSERT_QUERIES["insert_cve_range"]
try:
cursor.executemany(
insert_cve_range,
Expand All @@ -522,6 +552,21 @@ def populate_affected(self, affected_data, cursor, data_source):
except Exception as e:
LOGGER.info(f"Unable to insert data for {data_source} - {e}")

def populate_metrics(self):
cursor = self.db_open_and_get_cursor()
# Insert a row without specifying cve_metrics_id
insert_metrics = self.INSERT_QUERIES["insert_metrics"]
data = [
(1, "EPSS"),
(2, "CVSS-2"),
(3, "CVSS-3"),
]
# Execute the insert query for each row
for row in data:
cursor.execute(insert_metrics, row)
self.connection.commit()
self.db_close()

def clear_cached_data(self) -> None:
self.create_cache_backup()
if self.cachedir.exists():
Expand Down Expand Up @@ -639,6 +684,7 @@ def db_open_and_get_cursor(self) -> sqlite3.Cursor:
def db_close(self) -> None:
"""Closes connection to sqlite database."""
if self.connection:
self.connection.commit()
self.connection.close()
self.connection = None

Expand Down Expand Up @@ -712,12 +758,19 @@ def create_exploit_db(self):
self.db_close()

def populate_exploit_db(self, exploits):
(_, _, insert_exploit) = self.insert_queries()
insert_exploit = self.INSERT_QUERIES["insert_exploit"]
cursor = self.db_open_and_get_cursor()
cursor.executemany(insert_exploit, exploits)
self.connection.commit()
self.db_close()

def store_epss_data(self):
insert_cve_metrics = self.INSERT_QUERIES["insert_cve_metrics"]
cursor = self.db_open_and_get_cursor()
cursor.executemany(insert_cve_metrics, self.epss_data)
self.connection.commit()
self.db_close()

def dict_factory(self, cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
Expand Down Expand Up @@ -866,7 +919,6 @@ def db_to_json(self, path, private_key, passphrase):
shutil.rmtree(temp_gnupg_home)

def json_to_db(self, cursor, db_column, json_data):
(insert_severity, insert_cve_range, insert_exploit) = self.insert_queries()
columns = []
for data in json_data:
column = list(data.keys())
Expand All @@ -882,11 +934,15 @@ def json_to_db(self, cursor, db_column, json_data):
values.append(list(value))

if db_column == "cve_exploited":
cursor.executemany(insert_exploit, values)
cursor.executemany(self.INSERT_QUERIES["insert_exploit"], values)
elif db_column == "cve_range":
cursor.executemany(insert_cve_range, values)
cursor.executemany(self.INSERT_QUERIES["insert_cve_range"], values)
elif db_column == "cve_severity":
cursor.executemany(insert_severity, values)
cursor.executemany(self.INSERT_QUERIES["insert_severity"], values)
elif db_column == "cve_metrics":
cursor.executemany(self.INSERT_QUERIES["insert_cve_metrics"], values)
elif db_column == "metrics":
cursor.executemany(self.INSERT_QUERIES["insert_metrics"], values)

def json_to_db_wrapper(self, path, pubkey, ignore_signature, log_signature_error):
try:
Expand Down
13 changes: 7 additions & 6 deletions cve_bin_tool/data_sources/nvd_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,13 @@ def format_data_api2(self, all_cve_entries):
# return list of versions
affects_list = []
if "configurations" in cve_item:
for node in cve_item["configurations"][0]["nodes"]:
LOGGER.debug(f"Processing {node} for {cve_item['id']}")
affects_list.extend(self.parse_node_api2(node))
if "children" in node:
for child in node["children"]:
affects_list.extend(self.parse_node_api2(child))
for configuration in cve_item["configurations"]:
for node in configuration["nodes"]:
self.LOGGER.debug(f"Processing {node} for {cve_item['id']}")
affects_list.extend(self.parse_node_api2(node))
if "children" in node:
for child in node["children"]:
affects_list.extend(self.parse_node_api2(child))
else:
LOGGER.debug(f"No configuration information for {cve_item['id']}")
for affects in affects_list:
Expand Down
3 changes: 2 additions & 1 deletion cve_bin_tool/sbom_manager/spdx_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def parse_spdx_tag(self, sbom_file: str) -> list[list[str]]:
package = line_elements[1].strip().rstrip("\n")
version = None
if line_elements[0] == "PackageVersion":
version = line_elements[1].strip().rstrip("\n")
# Version may contain :
version = line[16:].strip().rstrip("\n")
version = version.split("-")[0]
version = version.split("+")[0]
modules.append([package, version])
Expand Down
Loading

0 comments on commit 80fd618

Please sign in to comment.