diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b0884bdfc8..b10af6df63 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -26,7 +26,7 @@ repos:
hooks:
- id: pyupgrade
exclude: ^fuzz/generated/
- args: ["--py38-plus"]
+ args: ["--py39-plus"]
- repo: https://github.com/pycqa/flake8
rev: 7.2.0
diff --git a/cve_bin_tool/cli.py b/cve_bin_tool/cli.py
index f1bfd7342e..a15c66212b 100644
--- a/cve_bin_tool/cli.py
+++ b/cve_bin_tool/cli.py
@@ -96,7 +96,7 @@ def main(argv=None):
"""Scan a binary file for certain open source libraries that may have CVEs"""
if sys.version_info < (3, 8):
raise OSError(
- "Python no longer provides security updates for version 3.7 as of June 2023. Please upgrade to python 3.8+ to use CVE Binary Tool."
+ "Python no longer provides security updates for version 3.8 as of October 2024. Please upgrade to Python 3.9+ to use CVE Binary Tool."
)
argv = argv or sys.argv
diff --git a/cve_bin_tool/csv2cve.py b/cve_bin_tool/csv2cve.py
index dee8ef1a90..7c591fa080 100644
--- a/cve_bin_tool/csv2cve.py
+++ b/cve_bin_tool/csv2cve.py
@@ -18,7 +18,7 @@ def main(argv: list[str] | None = None):
"""Used to scan a .csv file that lists the dependencies."""
if sys.version_info < (3, 8):
raise OSError(
- "Python no longer provides security updates for version 3.7 as of June 2023. Please upgrade to python 3.8+ to use CVE Binary Tool."
+ "Python no longer provides security updates for version 3.8 as of October 2024. Please upgrade to Python 3.9+ to use CVE Binary Tool."
)
logger: logging.Logger = LOGGER.getChild("CSV2CVE")
argv = argv or sys.argv
diff --git a/cve_bin_tool/cve_scanner.py b/cve_bin_tool/cve_scanner.py
index 0ea093a3cb..563d9a6c60 100644
--- a/cve_bin_tool/cve_scanner.py
+++ b/cve_bin_tool/cve_scanner.py
@@ -7,7 +7,6 @@
from logging import Logger
from pathlib import Path
from string import ascii_lowercase
-from typing import DefaultDict, Dict, List
from rich.console import Console
@@ -19,6 +18,8 @@
from cve_bin_tool.util import CVE, CVEData, ProductInfo, Remarks, VersionInfo
from cve_bin_tool.version_compare import Version
+# from typing import Dict, List
+
class CVEScanner:
"""
@@ -27,13 +28,13 @@ class CVEScanner:
products_with_cve: int
products_without_cve: int
- all_cve_data: DefaultDict[ProductInfo, CVEData]
- all_cve_version_info: Dict[str, VersionInfo]
+ all_cve_data: defaultdict[ProductInfo, CVEData]
+ all_cve_version_info: dict[str, VersionInfo]
RANGE_UNSET: str = ""
dbname: str = str(Path(DISK_LOCATION_DEFAULT) / DBNAME)
CONSOLE: Console = Console(file=sys.stderr, theme=cve_theme)
- ALPHA_TO_NUM: Dict[str, int] = dict(zip(ascii_lowercase, range(26)))
+ ALPHA_TO_NUM: dict[str, int] = dict(zip(ascii_lowercase, range(26)))
def __init__(
self,
@@ -44,8 +45,8 @@ def __init__(
logger: Logger = None,
error_mode: ErrorMode = ErrorMode.TruncTrace,
check_exploits: bool = False,
- exploits_list: List[str] = [],
- disabled_sources: List[str] = [],
+ exploits_list: list[str] = [],
+ disabled_sources: list[str] = [],
):
self.logger = logger or LOGGER.getChild(self.__class__.__name__)
self.error_mode = error_mode
@@ -211,10 +212,10 @@ def get_cves(self, product_info: ProductInfo, triage_data: TriageData):
)
product_info_data: CVEData | None = self.all_cve_data.get(product_info)
- prev_cves: List[CVE] = (
+ prev_cves: list[CVE] = (
product_info_data.get("cves", []) if product_info_data is not None else [] # type: ignore
)
- cves: List[CVE] = []
+ cves: list[CVE] = []
# Go through and get all the severities
if cve_list:
@@ -385,7 +386,7 @@ def filter_triage_data(self):
Filter out triage data that is not relevant to the CVEs found,
specifically those marked as NotAffected or FalsePositives.
"""
- to_delete: List[ProductInfo] = []
+ to_delete: list[ProductInfo] = []
for product_info, cve_data in self.all_cve_data.items():
original_cves = cve_data["cves"]
diff --git a/cve_bin_tool/input_engine.py b/cve_bin_tool/input_engine.py
index 3a90f959b4..9e9ab70e0d 100644
--- a/cve_bin_tool/input_engine.py
+++ b/cve_bin_tool/input_engine.py
@@ -11,9 +11,10 @@
import csv
import json
from collections import defaultdict
+from collections.abc import Iterable
from logging import Logger
from pathlib import Path
-from typing import Any, DefaultDict, Dict, Iterable, Set, Union
+from typing import Any, Union
from cve_bin_tool.cvedb import CVEDB
from cve_bin_tool.error_handler import (
@@ -27,7 +28,7 @@
from cve_bin_tool.util import ProductInfo, Remarks
# TriageData is dictionary of cve_number mapped to dictionary of remarks, comments and custom severity
-TriageData = Dict[str, Union[Dict[str, Any], Set[str]]]
+TriageData = dict[str, Union[dict[str, Any], set[str]]]
class InputEngine:
@@ -37,13 +38,13 @@ class InputEngine:
This class is responsible for parsing various input file formats (CSV, JSON) in the CVE Bin Tool.
Attributes:
- - parsed_data (DefaultDict[ProductInfo, TriageData]): Dictionary containing parsed input data.
+ - parsed_data (defaultdict[ProductInfo, TriageData]): Dictionary containing parsed input data.
Methods:
- __init__(self, filename: str, logger: Logger = None, error_mode=ErrorMode.TruncTrace, filetype="autodetect"):
Initializes the InputEngine with the specified filename, logger, error mode, and filetype.
- - parse_input(self) -> DefaultDict[ProductInfo, TriageData]:
+ - parse_input(self) -> defaultdict[ProductInfo, TriageData]:
Parses the input file based on its type (CSV, JSON) and returns the parsed data.
- input_csv(self) -> None:
@@ -58,7 +59,7 @@ class InputEngine:
"""
# parsed_data is a dictionary of vendor, product, version mapped to TriageData
- parsed_data: DefaultDict[ProductInfo, TriageData]
+ parsed_data: defaultdict[ProductInfo, TriageData]
def __init__(
self,
@@ -85,12 +86,12 @@ def __init__(
# Connect to the database
self.cvedb = CVEDB(version_check=False)
- def parse_input(self) -> DefaultDict[ProductInfo, TriageData]:
+ def parse_input(self) -> defaultdict[ProductInfo, TriageData]:
"""
Parses the input file and returns the parsed data.
Returns:
- - DefaultDict[ProductInfo, TriageData]: Parsed input data.
+ - defaultdict[ProductInfo, TriageData]: Parsed input data.
"""
@@ -135,7 +136,7 @@ def input_json(self) -> None:
self.parse_data(set(json_data[0].keys()), json_data)
- def parse_data(self, fields: Set[str], data: Iterable) -> None:
+ def parse_data(self, fields: set[str], data: Iterable) -> None:
"""
Parses common data structure for CSV and JSON input formats.
diff --git a/cve_bin_tool/output_engine/util.py b/cve_bin_tool/output_engine/util.py
index 3ded2d86fc..82858c33e1 100644
--- a/cve_bin_tool/output_engine/util.py
+++ b/cve_bin_tool/output_engine/util.py
@@ -317,7 +317,7 @@ def group_cve_by_remark(
{
"cve_number": "CVE-XXX-XXX",
"severity": "High",
- "decription: "Lorem Ipsm",
+ "description: "Lorem Ipsm",
},
{...}
],
@@ -329,7 +329,7 @@ def group_cve_by_remark(
cve_by_product (List[CVE]): List of CVE(s) that needs to be grouped
Returns:
- DefaultDict[Remarks, List[Dict[str, str]]]: CVEs grouped by remark stored in default dict
+ defaultdict[Remarks, list[dict[str, str]]]: CVEs grouped by remark stored in default dict
"""
cve_by_remarks: defaultdict[Remarks, list[dict[str, str]]] = defaultdict(list)
for cve in cve_by_product:
diff --git a/cve_bin_tool/sbom_manager/parse.py b/cve_bin_tool/sbom_manager/parse.py
index c498b7925a..b2533254ef 100644
--- a/cve_bin_tool/sbom_manager/parse.py
+++ b/cve_bin_tool/sbom_manager/parse.py
@@ -35,7 +35,7 @@ class SBOMParse:
It provides methods for scanning SBOM files, parsing them, and retrieving vendor information.
Attributes:
- - sbom_data (DefaultDict[ProductInfo, TriageData]): Dictionary containing parsed SBOM data.
+ - sbom_data (defaultdict[ProductInfo, TriageData]): Dictionary containing parsed SBOM data.
"""
@@ -147,7 +147,7 @@ def common_prefix_split(self, product, version) -> list[ProductInfo]:
if not found_common_prefix:
# if vendor not found after removing common prefix try splitting it
LOGGER.debug(
- f"No Vendor found for {product}, trying splitted product. "
+ f"No Vendor found for {product}, trying split product. "
"Some results may be inaccurate due to vendor identification limitations."
)
splitted_product = product.split("-")
diff --git a/cve_bin_tool/strings.py b/cve_bin_tool/strings.py
index 7ae84b8d36..61e0987f3d 100644
--- a/cve_bin_tool/strings.py
+++ b/cve_bin_tool/strings.py
@@ -8,7 +8,7 @@
"""
import subprocess
-from typing import ClassVar, List, Set
+from typing import ClassVar
from cve_bin_tool.async_utils import FileIO, run_coroutine
from cve_bin_tool.util import inpath
@@ -18,7 +18,7 @@ class Strings:
"""Utility class for parsing files and extracting printable characters."""
# printable characters
- PRINTABLE: ClassVar[Set[int]] = set(range(32, 128))
+ PRINTABLE: ClassVar[set[int]] = set(range(32, 128))
# add tab to the printable character
PRINTABLE.add(9)
@@ -35,7 +35,7 @@ async def aio_parse(self) -> str:
str: The acuumulated printable characters from the file.
"""
async with FileIO(self.filename, "rb") as f:
- tmp: List[str] = []
+ tmp: list[str] = []
async for line in f:
for char in line:
# remove all unprintable characters
diff --git a/cve_bin_tool/util.py b/cve_bin_tool/util.py
index 11ee0533f4..db859d7da8 100644
--- a/cve_bin_tool/util.py
+++ b/cve_bin_tool/util.py
@@ -9,9 +9,12 @@
import os
import re
import sys
+from collections import defaultdict
+from collections.abc import Iterator
from enum import Enum
from pathlib import Path
-from typing import DefaultDict, Iterator, List, NamedTuple, Pattern, Set, Union
+from re import Pattern
+from typing import NamedTuple, Union
import requests
from packageurl import PackageURL
@@ -248,7 +251,7 @@ class VersionInfo(NamedTuple):
end_excluding: str
-class CVEData(DefaultDict[str, Union[List[CVE], Set[str]]]):
+class CVEData(defaultdict[str, Union[list[CVE], set[str]]]):
"""
A Class representing a dictionary of CVEs and paths
"""
diff --git a/cve_bin_tool/vex_manager/parse.py b/cve_bin_tool/vex_manager/parse.py
index b58d1fe1e0..1c25050c25 100644
--- a/cve_bin_tool/vex_manager/parse.py
+++ b/cve_bin_tool/vex_manager/parse.py
@@ -1,14 +1,15 @@
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: GPL-3.0-or-later
-from typing import Any, DefaultDict, Dict, Set, Union
+from collections import defaultdict
+from typing import Any, Union
from lib4vex.parser import VEXParser
from cve_bin_tool.log import LOGGER
from cve_bin_tool.util import ProductInfo, Remarks, decode_bom_ref, decode_purl
-TriageData = Dict[str, Union[Dict[str, Any], Set[str]]]
+TriageData = dict[str, Union[dict[str, Any], set[str]]]
class VEXParse:
@@ -24,7 +25,7 @@ class VEXParse:
Methods:
- __init__(self, filename: str, vextype: str, logger=None): Initializes the VEXParse object.
- - parse_vex(self) -> DefaultDict[ProductInfo, TriageData]: Parses the VEX file and extracts the necessary fields from the vulnerabilities.
+ - parse_vex(self) -> defaultdict[ProductInfo, TriageData]: Parses the VEX file and extracts the necessary fields from the vulnerabilities.
- process_metadata(self) -> None: Processes the metadata.
- process_product(self) -> None: Processes the product information.
- process_vulnerabilities(self, vulnerabilities) -> None: Processes the vulnerabilities and extracts the necessary fields.
@@ -63,7 +64,7 @@ def __init__(self, filename: str, vextype: str, logger=None):
self.parsed_data = {}
self.serialNumbers = set()
- def parse_vex(self) -> DefaultDict[ProductInfo, TriageData]:
+ def parse_vex(self) -> defaultdict[ProductInfo, TriageData]:
"""Parses the VEX file and extracts the necessary fields from the vulnerabilities."""
vexparse = VEXParser(vex_type=self.vextype)
vexparse.parse(self.filename)
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 526121ced7..76500bff8b 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -26,4 +26,4 @@ types-jsonschema
types-PyYAML
types-requests
types-setuptools
-types-toml
+types-toml
\ No newline at end of file
diff --git a/doc/MANUAL.md b/doc/MANUAL.md
index 568c17b66a..daa301ae97 100644
--- a/doc/MANUAL.md
+++ b/doc/MANUAL.md
@@ -369,7 +369,7 @@ On Windows, it requires
- `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](https://github.com/mcmilk/7-Zip-zstd)
+If you want to run our test-suite or scan a zstd compressed file, We recommend installing this [7-zip-zstd](https://github.com/mcmilk/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..
@@ -537,7 +537,7 @@ 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
+python 3.10+ 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
@@ -1165,7 +1165,7 @@ haxx,curl,7.34.0,CVE-2014-0139,MEDIUM,Unexplored,
haxx , curl , 7.34.0 , CVE-2014-0015, MEDIUM
"
style="width:100%;white-space:pre;">
- formated console output
+ formatted console output
4. `--format html` - creates a report in html format according to the specified HTML theme.
@@ -1197,7 +1197,7 @@ haxx,curl,7.34.0,CVE-2014-0139,MEDIUM,Unexplored,
libjpeg-turbo, 2.0.1, 2
ssh-ssh2, 2.0, 1"
style="width:100%;white-space:pre;">
- formated HTML report
+ formatted HTML report
The unexplored and new CVEs will be highlighted, it will look something like this:
@@ -1214,7 +1214,7 @@ The unexplored and new CVEs will be highlighted, it will look something like thi
sun, sunos, 5.4, 127,
ssh, ssh2, 2.0, 4"
style="width:100%;white-space:pre;">
- formated HTML report
+ formatted HTML report
You can also filter scanned products by remark:
@@ -1230,7 +1230,7 @@ You can also filter scanned products by remark:
mit, kerberos, 1.15.1, 3,
"
style="width:100%;white-space:pre;">
- formated HTML report
+ formatted HTML report
5. `--format pdf` - creates a report in PDF format.
diff --git a/setup.py b/setup.py
index 54c18248d5..ad7bae29f2 100644
--- a/setup.py
+++ b/setup.py
@@ -35,7 +35,7 @@
url="https://github.com/intel/cve-bin-tool",
license="GPL-3.0-or-later",
keywords=["security", "tools", "CVE"],
- python_requires=">=3.8",
+ python_requires=">=3.10",
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
diff --git a/test/README.md b/test/README.md
index d04a607a4a..7c8b014ae5 100644
--- a/test/README.md
+++ b/test/README.md
@@ -74,14 +74,14 @@ The recommended way to do this yourself is to use python's `virtualenv`
You can set up virtualenv for all these environments:
```console
-virtualenv -p python3.8 venv3.8
-virtualenv -p python3.9 venv3.9
+virtualenv -p python3.11 venv3.11
+virtualenv -p python3.12 venv3.12
```
-To activate one of these (the example uses 3.8), run the tests, and deactivate:
+To activate one of these (the example uses 3.11), run the tests, and deactivate:
```console
-source venv3.8/bin/activate
+source venv3.11/bin/activate
pytest
deactivate
diff --git a/test/test_util.py b/test/test_util.py
index ed191ca4a0..8317a8593f 100644
--- a/test/test_util.py
+++ b/test/test_util.py
@@ -5,7 +5,7 @@
CVE-bin-tool util tests
"""
import inspect
-from typing import DefaultDict
+from collections import defaultdict
from cve_bin_tool.cve_scanner import CVEScanner
from cve_bin_tool.util import CVEData, ProductInfo, inpath
@@ -35,7 +35,7 @@ def test_cve_scanner(self):
instance_attrs = vars(CVEScanner)["__annotations__"]
assert (
- instance_attrs["all_cve_data"] == DefaultDict[ProductInfo, CVEData]
+ instance_attrs["all_cve_data"] == defaultdict[ProductInfo, CVEData]
), "Type of all_cve_data has been changed. Make sure it isn't breaking OutputEngine!"