From 9c3f88c75dabbc29ac897cf3088262485cef3832 Mon Sep 17 00:00:00 2001 From: Aryan Bakliwal Date: Sun, 17 Nov 2024 20:00:46 +0530 Subject: [PATCH 1/3] feat(parser): add conan parser Signed-off-by: Aryan Bakliwal --- cve_bin_tool/parsers/__init__.py | 1 + cve_bin_tool/parsers/ccpp.py | 62 ++++++++++++++++++++++++++++++++ doc/MANUAL.md | 9 ++++- test/language_data/conan.lock | 10 ++++++ test/test_language_scanner.py | 14 ++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 cve_bin_tool/parsers/ccpp.py create mode 100644 test/language_data/conan.lock diff --git a/cve_bin_tool/parsers/__init__.py b/cve_bin_tool/parsers/__init__.py index 5ed25c87ad..8394ccebd0 100644 --- a/cve_bin_tool/parsers/__init__.py +++ b/cve_bin_tool/parsers/__init__.py @@ -26,6 +26,7 @@ "perl", "dart", "env", + "ccpp", ] diff --git a/cve_bin_tool/parsers/ccpp.py b/cve_bin_tool/parsers/ccpp.py new file mode 100644 index 0000000000..6a4e2d5e11 --- /dev/null +++ b/cve_bin_tool/parsers/ccpp.py @@ -0,0 +1,62 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: GPL-3.0-or-later +"""Python script containing all functionalities related to parsing of C/C++ conan.lock files.""" + +import json +import re + +from cve_bin_tool.parsers import Parser + + +class CCppParser(Parser): + """Parser for C/C++ conan.lock files""" + + PARSER_MATCH_FILENAMES = [ + "conan.lock", + ] + + def __init__(self, cve_db, logger): + super().__init__(cve_db, logger) + self.purl_pkg_type = "conan" + + def generate_purl(self, product, vendor="", version="", qualifier={}, subpath=None): + """Generates PURL after normalizing all components.""" + product = re.sub(r"[^a-zA-Z0-9._-]", "", product).lower() + + if not product: + return None + + purl = super().generate_purl( + product, + vendor, + version, + qualifier, + subpath, + ) + + return purl + + def run_checker(self, filename): + """Parse the file and yield valid PURLs.""" + self.filename = filename + with open(self.filename) as fh: + data = json.load(fh) + requires = data["requires"] + build_requires = data["build_requires"] + if requires: + for require in requires: + product = require.split("#")[0].split("/")[0] + version = require.split("#")[0].split("/")[1] + purl = self.generate_purl(product) + vendor = self.get_vendor(purl, product, version) + if vendor is not None: + yield from vendor + if build_requires: + for build_require in build_requires: + product = build_require.split("#")[0].split("/")[0] + version = build_require.split("#")[0].split("/")[1] + purl = self.generate_purl(product) + vendor = self.get_vendor(purl, product, version) + if vendor is not None: + yield from vendor + self.logger.debug(f"Done scanning file: {self.filename}") diff --git a/doc/MANUAL.md b/doc/MANUAL.md index 4a7644afff..6eea193c78 100644 --- a/doc/MANUAL.md +++ b/doc/MANUAL.md @@ -92,6 +92,7 @@ - [Perl](#perl) - [PHP](#php) - [Dart](#dart) + - [C/C++](#cc) - [Feedback \& Contributions](#feedback--contributions) - [Security Issues](#security-issues) @@ -1520,10 +1521,16 @@ Here's an example of what a [`composer.lock`](https://github.com/intel/cve-bin-t ### 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. +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`](https://github.com/intel/cve-bin-tool/blob/main/test/language_data/pubspec.lock) file might look like. +### C/C++ + +The scanner examines the `conan.lock` file, generated by the Conan dependency and package manager for C and C++. The package names and versions are used to search the database for vulnerabilities. + +Here's an example of what a [`conan.lock`](https://github.com/intel/cve-bin-tool/blob/main/test/language_data/conan.lock) file might look like. + ## Feedback & Contributions Bugs and feature requests can be made via [GitHub issues](https://github.com/intel/cve-bin-tool/issues). diff --git a/test/language_data/conan.lock b/test/language_data/conan.lock new file mode 100644 index 0000000000..d30bb36a92 --- /dev/null +++ b/test/language_data/conan.lock @@ -0,0 +1,10 @@ +{ + "version": "0.5", + "requires": [ + "zlib/1.2.11#fca992a7d96a1b92bd956caa8a97d18f%1705999194.642", + "openssl/3.0.1w#a8f0792d7c5121b954578a7149d23e03%1717541485.78" + ], + "build_requires": [], + "python_requires": [], + "config_requires": [] +} \ No newline at end of file diff --git a/test/test_language_scanner.py b/test/test_language_scanner.py index ec480b5287..ba928b3c71 100644 --- a/test/test_language_scanner.py +++ b/test/test_language_scanner.py @@ -162,6 +162,8 @@ class TestLanguageScanner: DART_PRODUCTS = ["dio", "archive"] + CONAN_PRODUCTS = ["zlib", "openssl"] + @classmethod def setup_class(cls): cls.cvedb = CVEDB() @@ -341,6 +343,18 @@ def test_language_package_none_found(self, filename: str) -> None: ) ], ), + pytest.param( + str(TEST_FILE_PATH / "conan.lock"), + parsers.ccpp.CCppParser, + CONAN_PRODUCTS, + "conan", + marks=[ + pytest.mark.skipif( + not LONG_TESTS(), + reason="Test reduction in short tests", + ) + ], + ), ], ) def test_language_package( From f814b59238f6c36f23fc8668d62913e8d88cef67 Mon Sep 17 00:00:00 2001 From: Aryan Bakliwal Date: Sun, 24 Nov 2024 10:25:20 +0530 Subject: [PATCH 2/3] feat(parser): add example and test build_requires Signed-off-by: Aryan Bakliwal --- cve_bin_tool/parsers/ccpp.py | 5 ++++- test/language_data/conan.lock | 4 +++- test/test_language_scanner.py | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/cve_bin_tool/parsers/ccpp.py b/cve_bin_tool/parsers/ccpp.py index 6a4e2d5e11..8d4452e940 100644 --- a/cve_bin_tool/parsers/ccpp.py +++ b/cve_bin_tool/parsers/ccpp.py @@ -9,7 +9,10 @@ class CCppParser(Parser): - """Parser for C/C++ conan.lock files""" + """ + Parser for C/C++ conan.lock files based on + https://docs.conan.io/2/tutorial/versioning/lockfiles.html + """ PARSER_MATCH_FILENAMES = [ "conan.lock", diff --git a/test/language_data/conan.lock b/test/language_data/conan.lock index d30bb36a92..19bd5cdf56 100644 --- a/test/language_data/conan.lock +++ b/test/language_data/conan.lock @@ -4,7 +4,9 @@ "zlib/1.2.11#fca992a7d96a1b92bd956caa8a97d18f%1705999194.642", "openssl/3.0.1w#a8f0792d7c5121b954578a7149d23e03%1717541485.78" ], - "build_requires": [], + "build_requires": [ + "cmake/3.22.6#f305019023c2db74d1001c5afa5cf362" + ], "python_requires": [], "config_requires": [] } \ No newline at end of file diff --git a/test/test_language_scanner.py b/test/test_language_scanner.py index ba928b3c71..95d6b19c41 100644 --- a/test/test_language_scanner.py +++ b/test/test_language_scanner.py @@ -162,7 +162,7 @@ class TestLanguageScanner: DART_PRODUCTS = ["dio", "archive"] - CONAN_PRODUCTS = ["zlib", "openssl"] + CONAN_PRODUCTS = ["zlib", "openssl", "cmake"] @classmethod def setup_class(cls): From add8cea2e8e30895439d15468908e65db8b13e29 Mon Sep 17 00:00:00 2001 From: Aryan Bakliwal Date: Wed, 4 Dec 2024 11:01:13 +0530 Subject: [PATCH 3/3] feat(parser): add conan to expect.txt Signed-off-by: Aryan Bakliwal --- .github/actions/spelling/expect.txt | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index fd3171373d..ae0a8c1147 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -1,16 +1,5 @@ -Interoperability +conan cyclonedx -rdf +Interoperability sbom -spdx swid -aiohttp -cdx -cwes -getbootstrap -GMS -NOTKNOWN -pyyaml -skontar -Svunknown -urllib