nvd-client 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nvd_client/__init__.py +15 -0
- nvd_client/api.py +305 -0
- nvd_client/exceptions.py +40 -0
- nvd_client/utils.py +48 -0
- nvd_client-0.1.1.dist-info/LICENSE +21 -0
- nvd_client-0.1.1.dist-info/METADATA +99 -0
- nvd_client-0.1.1.dist-info/RECORD +9 -0
- nvd_client-0.1.1.dist-info/WHEEL +5 -0
- nvd_client-0.1.1.dist-info/top_level.txt +1 -0
nvd_client/__init__.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .exceptions import InvalidParametersError, InvalidCVEIDError, InvalidDateFormatError
|
|
2
|
+
from .api import NvdApi
|
|
3
|
+
|
|
4
|
+
__version__ = '0.1.0'
|
|
5
|
+
__author__ = 'Ahur4'
|
|
6
|
+
__author_email__ = 'ahur4.rahmani@gmail.com'
|
|
7
|
+
__license__ = 'MIT'
|
|
8
|
+
__copyright__ = 'Copyright 2024, Ahur4'
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"InvalidDateFormatError",
|
|
12
|
+
"InvalidCVEIDError",
|
|
13
|
+
"InvalidParametersError",
|
|
14
|
+
"NvdApi",
|
|
15
|
+
]
|
nvd_client/api.py
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
from typing import Dict, List, Optional, Union
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
from nvd_client.utils import validate_and_convert_dates, validate_cve_id
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class NvdApi:
|
|
9
|
+
"""
|
|
10
|
+
A class to interact with the NVD API for fetching CVE data.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
api_key (Optional[str]): The API key for authenticating requests.
|
|
14
|
+
api_key (Optional[str]): The Socks5 Proxy.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, api_key: Optional[str] = None, proxy: Optional[str] = None) -> None:
|
|
18
|
+
"""
|
|
19
|
+
Initialize the NvdApi class.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
api_key (Optional[str]): The API key for authenticating requests. Default is None.
|
|
23
|
+
api_key (Optional[str]): The Socks5 Proxy.
|
|
24
|
+
"""
|
|
25
|
+
self.proxy: Optional[str] = proxy
|
|
26
|
+
self.api_key: Optional[str] = api_key
|
|
27
|
+
self.base_url_cve: str = 'https://services.nvd.nist.gov/rest/json/cves/2.0'
|
|
28
|
+
self.base_url_cpe: str = 'https://services.nvd.nist.gov/rest/json/cpematch/2.0'
|
|
29
|
+
|
|
30
|
+
def __str__(self) -> str:
|
|
31
|
+
"""
|
|
32
|
+
Return a string representation of the NvdApi class.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
str: A string representation of the class.
|
|
36
|
+
"""
|
|
37
|
+
return "What are you looking for?"
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def _verifier(params: Dict[str, Union[str, int]]) -> str:
|
|
41
|
+
"""
|
|
42
|
+
Construct query string from parameters dictionary.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
params (Dict[str, Union[str, int]]): The parameters' dictionary.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
str: The query string constructed from the parameters.
|
|
49
|
+
"""
|
|
50
|
+
return "&".join([f"{k}={v}" for k, v in params.items()])
|
|
51
|
+
|
|
52
|
+
def _make_request(
|
|
53
|
+
self,
|
|
54
|
+
params: Optional[Dict[str, Union[str, int]]] = None,
|
|
55
|
+
type_of: str = "cve",
|
|
56
|
+
proxy: Optional[str] = None,
|
|
57
|
+
) -> Optional[Dict[str, Union[str, int, List, Dict]]]:
|
|
58
|
+
"""
|
|
59
|
+
Make a request to the NVD API with the provided parameters.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
params (Optional[Dict[str, Union[str, int]]]): The parameters for the API request. Default is None.
|
|
63
|
+
type_of (str): The parameters for the type of used api. default is cve.
|
|
64
|
+
|
|
65
|
+
Returns: Optional[Dict[str, Union[str, int, List, Dict]]]: The JSON response from the API, or None if an
|
|
66
|
+
error occurred.
|
|
67
|
+
"""
|
|
68
|
+
try:
|
|
69
|
+
parameters = self._verifier(params or {})
|
|
70
|
+
if type_of == "cve":
|
|
71
|
+
link = f"{self.base_url_cve}?{parameters}"
|
|
72
|
+
else:
|
|
73
|
+
link = f"{self.base_url_cpe}?{parameters}"
|
|
74
|
+
headers = {'apiKey': self.api_key} if self.api_key else {}
|
|
75
|
+
if self.proxy:
|
|
76
|
+
response = requests.get(link, headers=headers, proxies={"http": self.proxy, "https": self.proxy})
|
|
77
|
+
elif proxy:
|
|
78
|
+
response = requests.get(link, headers=headers, proxies={"http": proxy, "https": proxy})
|
|
79
|
+
else:
|
|
80
|
+
response = requests.get(link, headers=headers)
|
|
81
|
+
response.raise_for_status()
|
|
82
|
+
return response.json()
|
|
83
|
+
except Exception as e:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def get_all_cves(self, per_page: int = 2000, offset: int = 0, proxy: Optional[str] = None) -> Optional[Dict[str, Union[str, int, List, Dict]]]:
|
|
87
|
+
"""
|
|
88
|
+
Fetch all CVEs with pagination.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
per_page (int): The number of results per page. Default is 2000.
|
|
92
|
+
offset (int): The starting index for the results. Default is 0.
|
|
93
|
+
proxy (str): The proxy to use. Default is None.
|
|
94
|
+
|
|
95
|
+
Returns: Optional[Dict[str, Union[str, int, List, Dict]]]: The JSON response from the API, or None if an
|
|
96
|
+
error occurred.
|
|
97
|
+
"""
|
|
98
|
+
parameters = {
|
|
99
|
+
'resultsPerPage': per_page,
|
|
100
|
+
'startIndex': offset
|
|
101
|
+
}
|
|
102
|
+
if proxy:
|
|
103
|
+
return self._make_request(params=parameters, proxy=proxy)
|
|
104
|
+
return self._make_request(params=parameters)
|
|
105
|
+
|
|
106
|
+
def get_cve_by_id(self, cve_id: str, proxy: Optional[str] = None) -> Optional[Dict[str, Union[str, int, List, Dict]]]:
|
|
107
|
+
"""
|
|
108
|
+
Fetch a CVE by its ID.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
cve_id (str): The CVE ID to fetch.
|
|
112
|
+
proxy (str): The proxy to use. Default is None.
|
|
113
|
+
|
|
114
|
+
Returns: Optional[Dict[str, Union[str, int, List, Dict]]]: The JSON response from the API, or None if an
|
|
115
|
+
error occurred.
|
|
116
|
+
"""
|
|
117
|
+
if validate_cve_id(cve_id):
|
|
118
|
+
parameters = {"cveId": cve_id}
|
|
119
|
+
if proxy:
|
|
120
|
+
return self._make_request(params=parameters, proxy=proxy)
|
|
121
|
+
return self._make_request(params=parameters)
|
|
122
|
+
|
|
123
|
+
def get_cve_by_date(
|
|
124
|
+
self,
|
|
125
|
+
per_page: int = 2000,
|
|
126
|
+
offset: int = 0,
|
|
127
|
+
publish_start_date: Optional[str] = None,
|
|
128
|
+
publish_end_date: Optional[str] = None,
|
|
129
|
+
modify_start_date: Optional[str] = None,
|
|
130
|
+
modify_end_date: Optional[str] = None,
|
|
131
|
+
proxy: Optional[str] = None,
|
|
132
|
+
) -> Optional[Dict[str, Union[str, int, List, Dict]]]:
|
|
133
|
+
"""
|
|
134
|
+
Fetch CVEs by publication or modification date.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
per_page (int): The number of results per page. Default is 2000.
|
|
138
|
+
offset (int): The starting index for the results. Default is 0.
|
|
139
|
+
publish_start_date (Optional[str]): The start date for the publication date range. Default is None.
|
|
140
|
+
publish_end_date (Optional[str]): The end date for the publication date range. Default is None.
|
|
141
|
+
modify_start_date (Optional[str]): The start date for the modification date range. Default is None.
|
|
142
|
+
modify_end_date (Optional[str]): The end date for the modification date range. Default is None.
|
|
143
|
+
proxy (str): The proxy to use. Default is None.
|
|
144
|
+
|
|
145
|
+
Returns: Optional[Dict[str, Union[str, int, List, Dict]]]: The JSON response from the API, or None if an
|
|
146
|
+
error occurred.
|
|
147
|
+
"""
|
|
148
|
+
parameters: Dict[str, Union[str, int, List, Dict]] = {}
|
|
149
|
+
|
|
150
|
+
publish_start_date, publish_end_date = validate_and_convert_dates(
|
|
151
|
+
start_date=publish_start_date,
|
|
152
|
+
end_date=publish_end_date,
|
|
153
|
+
param_names=["publish_start_date", "publish_end_date"]
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
modify_start_date, modify_end_date = validate_and_convert_dates(
|
|
157
|
+
start_date=modify_start_date,
|
|
158
|
+
end_date=modify_end_date,
|
|
159
|
+
param_names=["modify_start_date", "modify_end_date"]
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
if publish_start_date and publish_end_date:
|
|
163
|
+
parameters.update(pubStartDate=publish_start_date, pubEndDate=publish_end_date)
|
|
164
|
+
|
|
165
|
+
if modify_start_date and modify_end_date:
|
|
166
|
+
parameters.update(lastModStartDate=modify_start_date, lastModEndDate=modify_end_date)
|
|
167
|
+
|
|
168
|
+
# Add more parameters as needed
|
|
169
|
+
parameters.update(resultsPerPage=per_page, startIndex=offset)
|
|
170
|
+
|
|
171
|
+
if proxy:
|
|
172
|
+
return self._make_request(params=parameters, proxy=proxy)
|
|
173
|
+
return self._make_request(params=parameters)
|
|
174
|
+
|
|
175
|
+
def get_cve_by_cpe(
|
|
176
|
+
self,
|
|
177
|
+
cpe_name: str,
|
|
178
|
+
per_page: int = 2000,
|
|
179
|
+
offset: int = 0,
|
|
180
|
+
publish_start_date: Optional[str] = None,
|
|
181
|
+
publish_end_date: Optional[str] = None,
|
|
182
|
+
modify_start_date: Optional[str] = None,
|
|
183
|
+
modify_end_date: Optional[str] = None,
|
|
184
|
+
proxy: Optional[str] = None,
|
|
185
|
+
) -> Optional[Dict[str, Union[str, int, List, Dict]]]:
|
|
186
|
+
"""
|
|
187
|
+
Fetch CVEs by CpeId.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
cpe_name (str): The CPE name to fetch.
|
|
191
|
+
per_page (int): The number of results per page. Default is 2000.
|
|
192
|
+
offset (int): The starting index for the results. Default is 0.
|
|
193
|
+
publish_start_date (Optional[str]): The start date for the publication date range. Default is None.
|
|
194
|
+
publish_end_date (Optional[str]): The end date for the publication date range. Default is None.
|
|
195
|
+
modify_start_date (Optional[str]): The start date for the modification date range. Default is None.
|
|
196
|
+
modify_end_date (Optional[str]): The end date for the modification date range. Default is None.
|
|
197
|
+
proxy (str): The proxy to use. Default is None.
|
|
198
|
+
|
|
199
|
+
Returns: Optional[Dict[str, Union[str, int, List, Dict]]]: The JSON response from the API, or None if an
|
|
200
|
+
error occurred.
|
|
201
|
+
"""
|
|
202
|
+
parameters = {}
|
|
203
|
+
|
|
204
|
+
publish_start_date, publish_end_date = validate_and_convert_dates(
|
|
205
|
+
start_date=publish_start_date,
|
|
206
|
+
end_date=publish_end_date,
|
|
207
|
+
param_names=["publish_start_date", "publish_end_date"]
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
modify_start_date, modify_end_date = validate_and_convert_dates(
|
|
211
|
+
start_date=modify_start_date,
|
|
212
|
+
end_date=modify_end_date,
|
|
213
|
+
param_names=["modify_start_date", "modify_end_date"]
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
if publish_start_date and publish_end_date:
|
|
217
|
+
parameters.update(pubStartDate=publish_start_date, pubEndDate=publish_end_date)
|
|
218
|
+
|
|
219
|
+
if modify_start_date and modify_end_date:
|
|
220
|
+
parameters.update(lastModStartDate=modify_start_date, lastModEndDate=modify_end_date)
|
|
221
|
+
|
|
222
|
+
parameters.update(resultsPerPage=per_page, startIndex=offset, cpeName=cpe_name)
|
|
223
|
+
|
|
224
|
+
if proxy:
|
|
225
|
+
return self._make_request(params=parameters, proxy=proxy)
|
|
226
|
+
return self._make_request(params=parameters)
|
|
227
|
+
|
|
228
|
+
def get_cpes_by_cve(
|
|
229
|
+
self,
|
|
230
|
+
cve_id: str,
|
|
231
|
+
per_page: int = 500,
|
|
232
|
+
offset: int = 0,
|
|
233
|
+
proxy: Optional[str] = None,
|
|
234
|
+
) -> Optional[Dict[str, Union[str, int, List, Dict]]]:
|
|
235
|
+
"""
|
|
236
|
+
Fetch CPEs by CveId.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
cve_id (str): The CVE ID to fetch.
|
|
240
|
+
per_page (int): The number of results per page. Default and Maximum is 500.
|
|
241
|
+
offset (int): The starting index for the results. Default is 0.
|
|
242
|
+
proxy (str): The proxy to use. Default is None.
|
|
243
|
+
|
|
244
|
+
Returns: List[Union[Dict[str, Any], Any]]: The JSON response from the API, or None if an
|
|
245
|
+
error occurred.
|
|
246
|
+
"""
|
|
247
|
+
if validate_cve_id(cve_id):
|
|
248
|
+
parameters = {}
|
|
249
|
+
parameters.update(resultsPerPage=per_page, startIndex=offset, cveId=cve_id)
|
|
250
|
+
|
|
251
|
+
if proxy:
|
|
252
|
+
return self._make_request(params=parameters, type_of="cpe", proxy=proxy)
|
|
253
|
+
return self._make_request(params=parameters, type_of="cpe")
|
|
254
|
+
|
|
255
|
+
def get_cpes_by_criteria(
|
|
256
|
+
self,
|
|
257
|
+
criteria: str,
|
|
258
|
+
per_page: int = 500,
|
|
259
|
+
offset: int = 0,
|
|
260
|
+
proxy: Optional[str] = None,
|
|
261
|
+
) -> Optional[Dict[str, Union[str, int, List, Dict]]]:
|
|
262
|
+
"""
|
|
263
|
+
Fetch CPEs by CveId.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
criteria (str): The Criteria to fetch.
|
|
267
|
+
per_page (int): The number of results per page. Default and Maximum is 500.
|
|
268
|
+
offset (int): The starting index for the results. Default is 0.
|
|
269
|
+
proxy (str): The proxy to use. Default is None.
|
|
270
|
+
|
|
271
|
+
Returns: List[Union[Dict[str, Any], Any]]: The JSON response from the API, or None if an
|
|
272
|
+
error occurred.
|
|
273
|
+
"""
|
|
274
|
+
parameters = {}
|
|
275
|
+
parameters.update(resultsPerPage=per_page, startIndex=offset, matchStringSearch=criteria)
|
|
276
|
+
|
|
277
|
+
if proxy:
|
|
278
|
+
return self._make_request(params=parameters, type_of="cpe", proxy=proxy)
|
|
279
|
+
return self._make_request(params=parameters, type_of="cpe")
|
|
280
|
+
|
|
281
|
+
def get_cpes_by_criteria_name_id(
|
|
282
|
+
self,
|
|
283
|
+
criteria_name_id: str,
|
|
284
|
+
per_page: int = 500,
|
|
285
|
+
offset: int = 0,
|
|
286
|
+
proxy: Optional[str] = None,
|
|
287
|
+
) -> Optional[Dict[str, Union[str, int, List, Dict]]]:
|
|
288
|
+
"""
|
|
289
|
+
Fetch CPEs by CveId.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
criteria_name_id (str): The Criteria Name ID to fetch.
|
|
293
|
+
per_page (int): The number of results per page. Default and Maximum is 500.
|
|
294
|
+
offset (int): The starting index for the results. Default is 0.
|
|
295
|
+
proxy (str): The proxy to use. Default is None.
|
|
296
|
+
|
|
297
|
+
Returns: List[Union[Dict[str, Any], Any]]: The JSON response from the API, or None if an
|
|
298
|
+
error occurred.
|
|
299
|
+
"""
|
|
300
|
+
parameters = {}
|
|
301
|
+
parameters.update(resultsPerPage=per_page, startIndex=offset, matchCriteriaId=criteria_name_id)
|
|
302
|
+
|
|
303
|
+
if proxy:
|
|
304
|
+
return self._make_request(params=parameters, type_of="cpe", proxy=proxy)
|
|
305
|
+
return self._make_request(params=parameters, type_of="cpe")
|
nvd_client/exceptions.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class InvalidDateFormatError(Exception):
|
|
5
|
+
"""Exception raised for errors in the input date format."""
|
|
6
|
+
|
|
7
|
+
def __init__(self, date_str, message="Invalid date format. Please use YYYY-MM-DD."):
|
|
8
|
+
self.date_str = date_str
|
|
9
|
+
self.message = message
|
|
10
|
+
super().__init__(self.message)
|
|
11
|
+
|
|
12
|
+
def __str__(self):
|
|
13
|
+
return f'{self.date_str} -> {self.message}'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class InvalidParametersError(Exception):
|
|
17
|
+
"""Exception raised for invalid parameters."""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
missing_params: List[str],
|
|
22
|
+
message="Invalid parameter combination. Both parameters are required."
|
|
23
|
+
):
|
|
24
|
+
self.missing_params = missing_params
|
|
25
|
+
self.message = message
|
|
26
|
+
super().__init__(self.message)
|
|
27
|
+
|
|
28
|
+
def __str__(self):
|
|
29
|
+
return f'Missing or incomplete parameters: {", ".join(self.missing_params)} -> {self.message}'
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class InvalidCVEIDError(Exception):
|
|
33
|
+
"""Exception raised for errors in the input CVE ID."""
|
|
34
|
+
def __init__(self, cve_id: str, message="Invalid CVE ID format. Please use CVE-YYYY-NNNN format."):
|
|
35
|
+
self.cve_id = cve_id
|
|
36
|
+
self.message = message
|
|
37
|
+
super().__init__(self.message)
|
|
38
|
+
|
|
39
|
+
def __str__(self):
|
|
40
|
+
return f'{self.cve_id} -> {self.message}'
|
nvd_client/utils.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from .exceptions import InvalidDateFormatError, InvalidParametersError, InvalidCVEIDError
|
|
4
|
+
from typing import Optional, List
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def validate_date_format(date_str):
|
|
8
|
+
# Define the regex pattern for YYYY-MM-DD format
|
|
9
|
+
pattern = r'^\d{4}-\d{2}-\d{2}$'
|
|
10
|
+
# Check if the date_str matches the pattern
|
|
11
|
+
if re.match(pattern, date_str):
|
|
12
|
+
try:
|
|
13
|
+
# Try to parse the date to ensure it's a valid date
|
|
14
|
+
datetime.strptime(date_str, '%Y-%m-%d')
|
|
15
|
+
return True
|
|
16
|
+
except ValueError:
|
|
17
|
+
return False
|
|
18
|
+
else:
|
|
19
|
+
return False
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def convert_date_to_iso(date_str):
|
|
23
|
+
if validate_date_format(date_str):
|
|
24
|
+
# Parse the input date
|
|
25
|
+
date = datetime.strptime(date_str, '%Y-%m-%d')
|
|
26
|
+
# Convert to the desired format
|
|
27
|
+
iso_format_date = date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3]
|
|
28
|
+
return iso_format_date
|
|
29
|
+
else:
|
|
30
|
+
raise InvalidDateFormatError(date_str)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def validate_and_convert_dates(start_date: Optional[str], end_date: Optional[str], param_names: List[str]):
|
|
34
|
+
if start_date and end_date:
|
|
35
|
+
return convert_date_to_iso(start_date), convert_date_to_iso(end_date)
|
|
36
|
+
elif start_date or end_date:
|
|
37
|
+
raise InvalidParametersError(missing_params=param_names)
|
|
38
|
+
return None, None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def validate_cve_id(cve_id: str) -> bool:
|
|
42
|
+
# Define the regex pattern for CVE-YYYY-NNNN format
|
|
43
|
+
pattern = r'^CVE-\d{4}-\d{4,}$'
|
|
44
|
+
# Check if the cve_id matches the pattern
|
|
45
|
+
if re.match(pattern, cve_id):
|
|
46
|
+
return True
|
|
47
|
+
else:
|
|
48
|
+
raise InvalidCVEIDError(cve_id)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Ahur4
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: nvd-client
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A Python client for interacting with the National Vulnerability Database (NVD) API to fetch CVE data.
|
|
5
|
+
Home-page: https://github.com/ahur4/nvd-client
|
|
6
|
+
Author: Ahur4
|
|
7
|
+
Author-email: ahur4.rahmani@gmail.com
|
|
8
|
+
Keywords: vulnerability,nvd,national vulnerability database,nvd_client,nvd_client-api,ahur4,ahura rahmani,redteam,soc,vulnerability assessment,penetration testing
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: certifi ==2024.6.2
|
|
16
|
+
Requires-Dist: charset-normalizer ==3.3.2
|
|
17
|
+
Requires-Dist: idna ==3.7
|
|
18
|
+
Requires-Dist: requests[socks] ==2.32.3
|
|
19
|
+
Requires-Dist: urllib3 ==2.2.1
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# NVD API Client
|
|
23
|
+
|
|
24
|
+

|
|
25
|
+

|
|
26
|
+

|
|
27
|
+
[](https://t.me/Ahur4_Rahmani)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
A Python client for interacting with the National Vulnerability Database (NVD) API to fetch CVE data.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Fetch all CVEs with pagination
|
|
35
|
+
- Fetch CVE by its ID
|
|
36
|
+
- Fetch CVEs by publication or modification date
|
|
37
|
+
- Fetch CVEs by CPE name
|
|
38
|
+
- Other features coming soon...
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
You can install the package using pip:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
pip install nvd_client
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from nvd_client import NvdApi
|
|
52
|
+
|
|
53
|
+
# Initialize the API client
|
|
54
|
+
api_key = "your_api_key_here"
|
|
55
|
+
nvd_api = NvdApi(api_key)
|
|
56
|
+
|
|
57
|
+
# Fetch all CVEs
|
|
58
|
+
cves = nvd_api.get_all_cves(per_page=100, offset=0)
|
|
59
|
+
print(cves)
|
|
60
|
+
|
|
61
|
+
# Fetch a CVE by ID
|
|
62
|
+
cve = nvd_api.get_cve_by_id(cve_id="CVE-2024-30078")
|
|
63
|
+
print(cve)
|
|
64
|
+
|
|
65
|
+
# Fetch CVEs by publish or modify date range
|
|
66
|
+
cves_by_date = nvd_api.get_cve_by_date(
|
|
67
|
+
per_page=100,
|
|
68
|
+
offset=0,
|
|
69
|
+
publish_start_date="2021-01-01",
|
|
70
|
+
publish_end_date="2021-12-31"
|
|
71
|
+
)
|
|
72
|
+
print(cves_by_date)
|
|
73
|
+
|
|
74
|
+
# Fetch CVEs by CPE name
|
|
75
|
+
cves_by_cpe = nvd_api.get_cve_by_cpe(
|
|
76
|
+
cpe_name="cpe:2.3:o:microsoft:windows_10:1607:*:*:*:*:*:*:*",
|
|
77
|
+
per_page=100,
|
|
78
|
+
offset=0
|
|
79
|
+
)
|
|
80
|
+
print(cves_by_cpe)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Author
|
|
84
|
+
|
|
85
|
+
- Author: Ahur4
|
|
86
|
+
|
|
87
|
+
- Telegram: [@Ahura_rahmani](https://t.me/Ahura_rahmani)
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
This project is licensed under the MIT License. See the `LICENSE` file for details.
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
### Explanation:
|
|
95
|
+
1. **Features**: Lists the main functionalities provided by the module.
|
|
96
|
+
2. **Installation**: Provides instructions for installing the package using pip from PyPI.
|
|
97
|
+
3. **Usage**: Gives examples of how to initialize the client and use its methods.
|
|
98
|
+
4. **Author**: Provides your name and a link to your Telegram channel.
|
|
99
|
+
5. **License**: States that the project is licensed under the MIT License.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
nvd_client/__init__.py,sha256=JBBwBR214nMGV_ZG5dr06gNuL6Wu6EzneYLTLcjWTgo,392
|
|
2
|
+
nvd_client/api.py,sha256=aOh19xUXzg08FtyXxJCEZsbkmwieqakVII2FxfKIzCM,12667
|
|
3
|
+
nvd_client/exceptions.py,sha256=jah5qsid089419Cwq1fLY3SIgkdeGorj1daG3Z6qsOo,1314
|
|
4
|
+
nvd_client/utils.py,sha256=GpN4v4ONQAijtxJL49sxpmkJs3SZMziCxMT9r7uwrEY,1645
|
|
5
|
+
nvd_client-0.1.1.dist-info/LICENSE,sha256=sH516rZoWuam08PIkKJ7N9q8AR_KZZ67CttgY9Q5n7U,1081
|
|
6
|
+
nvd_client-0.1.1.dist-info/METADATA,sha256=rRIJ_SLq-K0pMAAYGZuEPuVxULkKfL224mtMmCPxHqQ,2906
|
|
7
|
+
nvd_client-0.1.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
8
|
+
nvd_client-0.1.1.dist-info/top_level.txt,sha256=Bt0KpXk1HXgHIzDg70YvgQaBzhBsBVwZHSAbTtsrOk4,11
|
|
9
|
+
nvd_client-0.1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nvd_client
|