From 0a88b9db0a4fe8a2c77db13c2afa986383242246 Mon Sep 17 00:00:00 2001 From: Francois Lesueur Date: Tue, 6 May 2025 10:59:58 +0200 Subject: [PATCH 1/3] feat: add since and pagination to get_vendor_product_vulnerabilities() --- pyvulnerabilitylookup/api.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/pyvulnerabilitylookup/api.py b/pyvulnerabilitylookup/api.py index 89f1470..931c556 100644 --- a/pyvulnerabilitylookup/api.py +++ b/pyvulnerabilitylookup/api.py @@ -155,14 +155,31 @@ def get_vendor_products(self, vendor: str) -> list[str]: r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'browse', vendor)))) return r.json() - def get_vendor_product_vulnerabilities(self, vendor: str, product: str) -> list[str]: + def get_vendor_product_vulnerabilities(self, vendor: str, product: str, since: date | datetime | None=None) -> list[str]: '''Get the the vulnerabilities per vendor and a specific product :param vendor: A vendor owning products (must be in the known vendor list) :param product: A product owned by that vendor + :param since: The date from which to get vulnerabilities ''' - r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'vulnerability', 'search', vendor, product)))) - return r.json() + + params = {} + if since: + if isinstance(since, datetime): + since = since.date() + params['since'] = since.isoformat() + + params['page'] = 1 + params['per_page'] = 100 + r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'vulnerability', 'search', vendor, product))), params=params) + res = r.json() + while r.json()['cvelistv5']: + params['page'] += 1 + r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'vulnerability', 'search', vendor, product))), params=params) + for source in r.json(): + res[source] = res.get(source, []) + r.json()[source] + + return res # #### Comments #### From 07a6f58cc03a468987b69f72502e656361f36802 Mon Sep 17 00:00:00 2001 From: Francois Lesueur Date: Fri, 9 May 2025 14:05:43 +0200 Subject: [PATCH 2/3] fix: mypy type declaration --- pyvulnerabilitylookup/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyvulnerabilitylookup/api.py b/pyvulnerabilitylookup/api.py index 931c556..36f94e0 100644 --- a/pyvulnerabilitylookup/api.py +++ b/pyvulnerabilitylookup/api.py @@ -163,7 +163,7 @@ def get_vendor_product_vulnerabilities(self, vendor: str, product: str, since: d :param since: The date from which to get vulnerabilities ''' - params = {} + params: dict[str, Any] = {} if since: if isinstance(since, datetime): since = since.date() From ea47f310b63594d7b798a4362fa1ed642c68ce69 Mon Sep 17 00:00:00 2001 From: Francois Lesueur Date: Fri, 9 May 2025 14:31:55 +0200 Subject: [PATCH 3/3] fix: end condition --- pyvulnerabilitylookup/api.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pyvulnerabilitylookup/api.py b/pyvulnerabilitylookup/api.py index 36f94e0..090fe51 100644 --- a/pyvulnerabilitylookup/api.py +++ b/pyvulnerabilitylookup/api.py @@ -170,14 +170,20 @@ def get_vendor_product_vulnerabilities(self, vendor: str, product: str, since: d params['since'] = since.isoformat() params['page'] = 1 - params['per_page'] = 100 + params['per_page'] = 10 r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'vulnerability', 'search', vendor, product))), params=params) res = r.json() - while r.json()['cvelistv5']: + r_length = 0 + for source in r.json(): + r_length += len(r.json()[source]) + + while r_length == params['per_page']: params['page'] += 1 r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'vulnerability', 'search', vendor, product))), params=params) + r_length = 0 for source in r.json(): res[source] = res.get(source, []) + r.json()[source] + r_length += len(r.json()[source]) return res