nvd-client 0.1.3.2__tar.gz

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.
@@ -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,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: nvd-client
3
+ Version: 0.1.3.2
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
+ Requires-Python: >=3.6
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: certifi==2024.6.2
14
+ Requires-Dist: charset-normalizer==3.3.2
15
+ Requires-Dist: idna==3.7
16
+ Requires-Dist: requests[socks]==2.32.3
17
+ Requires-Dist: urllib3==2.2.1
18
+ Requires-Dist: pytz==2025.2
19
+ Dynamic: author
20
+ Dynamic: author-email
21
+ Dynamic: classifier
22
+ Dynamic: description
23
+ Dynamic: description-content-type
24
+ Dynamic: home-page
25
+ Dynamic: keywords
26
+ Dynamic: license-file
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
30
+
31
+
32
+ # NVD API Client
33
+
34
+ ![PyPI](https://img.shields.io/pypi/v/nvd-client)
35
+ ![Daily Downloads](https://img.shields.io/pypi/dd/nvd-client)
36
+ ![Monthly Downloads](https://img.shields.io/pypi/dm/nvd-client)
37
+ [![Telegram-Channel](https://img.shields.io/badge/Telegram--Channel-Ahura_Rahmani-blue)](https://t.me/Ahur4_Rahmani)
38
+
39
+
40
+ A Python client for interacting with the National Vulnerability Database (NVD) API to fetch CVE data.
41
+
42
+ ## Features
43
+
44
+ - Fetch all CVEs with pagination
45
+ - Fetch CVE by its ID
46
+ - Fetch CVEs by publication or modification date
47
+ - Fetch CVEs by CPE name
48
+ - Other features coming soon...
49
+
50
+ ## Installation
51
+
52
+ You can install the package using pip:
53
+
54
+ ```sh
55
+ pip install nvd_client
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ```python
61
+ from nvd_client import NvdApi
62
+ from datetime import datetime, timedelta
63
+
64
+ # Initialize the API client
65
+ api_key = "your_api_key_here"
66
+ nvd_api = NvdApi(api_key)
67
+
68
+ # Fetch all CVEs
69
+ cves = nvd_api.get_all_cves(per_page=100, offset=0)
70
+ print(cves)
71
+
72
+ # Fetch a CVE by ID
73
+ cve = nvd_api.get_cve_by_id(cve_id="CVE-2024-30078")
74
+ print(cve)
75
+
76
+ # Fetch CVEs by publish or modify date range
77
+ cves_by_date = nvd_api.get_cve_by_date(
78
+ per_page=100,
79
+ offset=0,
80
+ publish_start_date=datetime.now() - timedelta(days=2),
81
+ publish_end_date=datetime.now()
82
+ )
83
+ print(cves_by_date)
84
+
85
+ # Fetch CVEs by CPE name
86
+ cves_by_cpe = nvd_api.get_cve_by_cpe(
87
+ cpe_name="cpe:2.3:o:microsoft:windows_10:1607:*:*:*:*:*:*:*",
88
+ per_page=100,
89
+ offset=0
90
+ )
91
+ print(cves_by_cpe)
92
+ ```
93
+
94
+ ## Author
95
+
96
+ - Author: Ahur4
97
+
98
+ - Telegram: [@Ahura_rahmani](https://t.me/Ahura_rahmani)
99
+
100
+ ## License
101
+
102
+ This project is licensed under the MIT License. See the `LICENSE` file for details.
103
+
104
+
105
+ ### Explanation:
106
+ 1. **Features**: Lists the main functionalities provided by the module.
107
+ 2. **Installation**: Provides instructions for installing the package using pip from PyPI.
108
+ 3. **Usage**: Gives examples of how to initialize the client and use its methods.
109
+ 4. **Author**: Provides your name and a link to your Telegram channel.
110
+ 5. **License**: States that the project is licensed under the MIT License.
@@ -0,0 +1,80 @@
1
+
2
+ # NVD API Client
3
+
4
+ ![PyPI](https://img.shields.io/pypi/v/nvd-client)
5
+ ![Daily Downloads](https://img.shields.io/pypi/dd/nvd-client)
6
+ ![Monthly Downloads](https://img.shields.io/pypi/dm/nvd-client)
7
+ [![Telegram-Channel](https://img.shields.io/badge/Telegram--Channel-Ahura_Rahmani-blue)](https://t.me/Ahur4_Rahmani)
8
+
9
+
10
+ A Python client for interacting with the National Vulnerability Database (NVD) API to fetch CVE data.
11
+
12
+ ## Features
13
+
14
+ - Fetch all CVEs with pagination
15
+ - Fetch CVE by its ID
16
+ - Fetch CVEs by publication or modification date
17
+ - Fetch CVEs by CPE name
18
+ - Other features coming soon...
19
+
20
+ ## Installation
21
+
22
+ You can install the package using pip:
23
+
24
+ ```sh
25
+ pip install nvd_client
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ```python
31
+ from nvd_client import NvdApi
32
+ from datetime import datetime, timedelta
33
+
34
+ # Initialize the API client
35
+ api_key = "your_api_key_here"
36
+ nvd_api = NvdApi(api_key)
37
+
38
+ # Fetch all CVEs
39
+ cves = nvd_api.get_all_cves(per_page=100, offset=0)
40
+ print(cves)
41
+
42
+ # Fetch a CVE by ID
43
+ cve = nvd_api.get_cve_by_id(cve_id="CVE-2024-30078")
44
+ print(cve)
45
+
46
+ # Fetch CVEs by publish or modify date range
47
+ cves_by_date = nvd_api.get_cve_by_date(
48
+ per_page=100,
49
+ offset=0,
50
+ publish_start_date=datetime.now() - timedelta(days=2),
51
+ publish_end_date=datetime.now()
52
+ )
53
+ print(cves_by_date)
54
+
55
+ # Fetch CVEs by CPE name
56
+ cves_by_cpe = nvd_api.get_cve_by_cpe(
57
+ cpe_name="cpe:2.3:o:microsoft:windows_10:1607:*:*:*:*:*:*:*",
58
+ per_page=100,
59
+ offset=0
60
+ )
61
+ print(cves_by_cpe)
62
+ ```
63
+
64
+ ## Author
65
+
66
+ - Author: Ahur4
67
+
68
+ - Telegram: [@Ahura_rahmani](https://t.me/Ahura_rahmani)
69
+
70
+ ## License
71
+
72
+ This project is licensed under the MIT License. See the `LICENSE` file for details.
73
+
74
+
75
+ ### Explanation:
76
+ 1. **Features**: Lists the main functionalities provided by the module.
77
+ 2. **Installation**: Provides instructions for installing the package using pip from PyPI.
78
+ 3. **Usage**: Gives examples of how to initialize the client and use its methods.
79
+ 4. **Author**: Provides your name and a link to your Telegram channel.
80
+ 5. **License**: States that the project is licensed under the MIT License.
@@ -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
+ ]
@@ -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")
@@ -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. date type must be datetime obj."):
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}'
@@ -0,0 +1,51 @@
1
+ import re
2
+ from datetime import datetime
3
+ from typing import Optional, List
4
+
5
+ import pytz
6
+
7
+ from nvd_client.exceptions import InvalidDateFormatError, InvalidParametersError, InvalidCVEIDError
8
+
9
+ # Use Iran's timezone
10
+ IRAN_TZ = pytz.timezone('Asia/Tehran')
11
+
12
+
13
+ def validate_date_format(date_str: str):
14
+ # Define the regex pattern for ISO 8601 format with timezone
15
+ pattern = r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}$'
16
+ # Check if the date_str matches the pattern
17
+ if re.match(pattern, date_str):
18
+ try:
19
+ # Parse the date to ensure it's a valid date
20
+ datetime.strptime(date_str, '%Y-%m-%dT%H:%M:%S.%f')
21
+ return True
22
+ except ValueError:
23
+ return False
24
+ return False
25
+
26
+
27
+ def convert_date_to_iso(date: datetime):
28
+ if isinstance(date, datetime):
29
+ # Convert to the desired ISO format without timezone information
30
+ iso_format_date = date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] # Truncate to milliseconds
31
+ return iso_format_date
32
+ else:
33
+ raise InvalidDateFormatError(f"Invalid datetime object: {date}")
34
+
35
+
36
+ def validate_and_convert_dates(start_date: Optional[datetime], end_date: Optional[datetime], param_names: List[str]):
37
+ if start_date and end_date:
38
+ return convert_date_to_iso(start_date), convert_date_to_iso(end_date)
39
+ elif start_date or end_date:
40
+ raise InvalidParametersError(missing_params=param_names)
41
+ return None, None
42
+
43
+
44
+ def validate_cve_id(cve_id: str) -> bool:
45
+ # Define the regex pattern for CVE-YYYY-NNNN format
46
+ pattern = r'^CVE-\d{4}-\d{4,}$'
47
+ # Check if the cve_id matches the pattern
48
+ if re.match(pattern, cve_id):
49
+ return True
50
+ else:
51
+ raise InvalidCVEIDError(cve_id)
@@ -0,0 +1,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: nvd-client
3
+ Version: 0.1.3.2
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
+ Requires-Python: >=3.6
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: certifi==2024.6.2
14
+ Requires-Dist: charset-normalizer==3.3.2
15
+ Requires-Dist: idna==3.7
16
+ Requires-Dist: requests[socks]==2.32.3
17
+ Requires-Dist: urllib3==2.2.1
18
+ Requires-Dist: pytz==2025.2
19
+ Dynamic: author
20
+ Dynamic: author-email
21
+ Dynamic: classifier
22
+ Dynamic: description
23
+ Dynamic: description-content-type
24
+ Dynamic: home-page
25
+ Dynamic: keywords
26
+ Dynamic: license-file
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
30
+
31
+
32
+ # NVD API Client
33
+
34
+ ![PyPI](https://img.shields.io/pypi/v/nvd-client)
35
+ ![Daily Downloads](https://img.shields.io/pypi/dd/nvd-client)
36
+ ![Monthly Downloads](https://img.shields.io/pypi/dm/nvd-client)
37
+ [![Telegram-Channel](https://img.shields.io/badge/Telegram--Channel-Ahura_Rahmani-blue)](https://t.me/Ahur4_Rahmani)
38
+
39
+
40
+ A Python client for interacting with the National Vulnerability Database (NVD) API to fetch CVE data.
41
+
42
+ ## Features
43
+
44
+ - Fetch all CVEs with pagination
45
+ - Fetch CVE by its ID
46
+ - Fetch CVEs by publication or modification date
47
+ - Fetch CVEs by CPE name
48
+ - Other features coming soon...
49
+
50
+ ## Installation
51
+
52
+ You can install the package using pip:
53
+
54
+ ```sh
55
+ pip install nvd_client
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ```python
61
+ from nvd_client import NvdApi
62
+ from datetime import datetime, timedelta
63
+
64
+ # Initialize the API client
65
+ api_key = "your_api_key_here"
66
+ nvd_api = NvdApi(api_key)
67
+
68
+ # Fetch all CVEs
69
+ cves = nvd_api.get_all_cves(per_page=100, offset=0)
70
+ print(cves)
71
+
72
+ # Fetch a CVE by ID
73
+ cve = nvd_api.get_cve_by_id(cve_id="CVE-2024-30078")
74
+ print(cve)
75
+
76
+ # Fetch CVEs by publish or modify date range
77
+ cves_by_date = nvd_api.get_cve_by_date(
78
+ per_page=100,
79
+ offset=0,
80
+ publish_start_date=datetime.now() - timedelta(days=2),
81
+ publish_end_date=datetime.now()
82
+ )
83
+ print(cves_by_date)
84
+
85
+ # Fetch CVEs by CPE name
86
+ cves_by_cpe = nvd_api.get_cve_by_cpe(
87
+ cpe_name="cpe:2.3:o:microsoft:windows_10:1607:*:*:*:*:*:*:*",
88
+ per_page=100,
89
+ offset=0
90
+ )
91
+ print(cves_by_cpe)
92
+ ```
93
+
94
+ ## Author
95
+
96
+ - Author: Ahur4
97
+
98
+ - Telegram: [@Ahura_rahmani](https://t.me/Ahura_rahmani)
99
+
100
+ ## License
101
+
102
+ This project is licensed under the MIT License. See the `LICENSE` file for details.
103
+
104
+
105
+ ### Explanation:
106
+ 1. **Features**: Lists the main functionalities provided by the module.
107
+ 2. **Installation**: Provides instructions for installing the package using pip from PyPI.
108
+ 3. **Usage**: Gives examples of how to initialize the client and use its methods.
109
+ 4. **Author**: Provides your name and a link to your Telegram channel.
110
+ 5. **License**: States that the project is licensed under the MIT License.
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ nvd_client/__init__.py
5
+ nvd_client/api.py
6
+ nvd_client/exceptions.py
7
+ nvd_client/utils.py
8
+ nvd_client.egg-info/PKG-INFO
9
+ nvd_client.egg-info/SOURCES.txt
10
+ nvd_client.egg-info/dependency_links.txt
11
+ nvd_client.egg-info/requires.txt
12
+ nvd_client.egg-info/top_level.txt
@@ -0,0 +1,6 @@
1
+ certifi==2024.6.2
2
+ charset-normalizer==3.3.2
3
+ idna==3.7
4
+ requests[socks]==2.32.3
5
+ urllib3==2.2.1
6
+ pytz==2025.2
@@ -0,0 +1 @@
1
+ nvd_client
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,31 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ long_description = open('README.md', 'r').read()
4
+
5
+ setup(
6
+ name="nvd-client",
7
+ version="0.1.3.2",
8
+ description="A Python client for interacting with the National Vulnerability Database (NVD) API to fetch CVE data.",
9
+ author="Ahur4",
10
+ author_email="ahur4.rahmani@gmail.com",
11
+ url="https://github.com/ahur4/nvd-client",
12
+ packages=find_packages(include=['nvd_client', 'nvd_client.*']),
13
+ install_requires=[
14
+ "certifi==2024.6.2",
15
+ "charset-normalizer==3.3.2",
16
+ "idna==3.7",
17
+ "requests[socks]==2.32.3",
18
+ "urllib3==2.2.1",
19
+ "pytz==2025.2"
20
+ ],
21
+ classifiers=[
22
+ "Programming Language :: Python :: 3",
23
+ ],
24
+ python_requires='>=3.6',
25
+ keywords=[
26
+ "vulnerability", "nvd", "national vulnerability database", "nvd_client", "nvd_client-api",
27
+ "ahur4", "ahura rahmani", "redteam", "soc", "vulnerability assessment", "penetration testing"
28
+ ],
29
+ long_description=long_description,
30
+ long_description_content_type='text/markdown',
31
+ )