12
12
13
13
__author__ = "Mario Rojas"
14
14
__license__ = "BSD 3-clause"
15
- __version__ = "1.3 .0"
15
+ __version__ = "1.4 .0"
16
16
__maintainer__ = "Mario Rojas"
17
17
__status__ = "Production"
18
18
@@ -67,32 +67,41 @@ def nist_check(cve_id):
67
67
if unique_cve .get ("cve" ).get ("cisaExploitAdd" ):
68
68
cisa_kev = True
69
69
70
+ try :
71
+ cpe = unique_cve .get ("cve" ).get ("configurations" )[0 ].get ("nodes" )[0 ].get ("cpeMatch" )[0 ].get ("criteria" )
72
+ except TypeError :
73
+ cpe = 'cpe:2.3:::::::::::'
74
+
70
75
# Collect CVSS Data
71
76
if unique_cve .get ("cve" ).get ("metrics" ).get ("cvssMetricV31" ):
72
77
for metric in unique_cve .get ("cve" ).get ("metrics" ).get ("cvssMetricV31" ):
73
78
results = {"cvss_version" : "CVSS 3.1" ,
74
79
"cvss_baseScore" : float (metric .get ("cvssData" ).get ("baseScore" )),
75
80
"cvss_severity" : metric .get ("cvssData" ).get ("baseSeverity" ),
76
- "cisa_kev" : cisa_kev }
81
+ "cisa_kev" : cisa_kev ,
82
+ "cpe" : cpe }
77
83
return results
78
84
elif unique_cve .get ("cve" ).get ("metrics" ).get ("cvssMetricV30" ):
79
85
for metric in unique_cve .get ("cve" ).get ("metrics" ).get ("cvssMetricV30" ):
80
86
results = {"cvss_version" : "CVSS 3.0" ,
81
87
"cvss_baseScore" : float (metric .get ("cvssData" ).get ("baseScore" )),
82
88
"cvss_severity" : metric .get ("cvssData" ).get ("baseSeverity" ),
83
- "cisa_kev" : cisa_kev }
89
+ "cisa_kev" : cisa_kev ,
90
+ "cpe" : cpe }
84
91
return results
85
92
elif unique_cve .get ("cve" ).get ("metrics" ).get ("cvssMetricV2" ):
86
93
for metric in unique_cve .get ("cve" ).get ("metrics" ).get ("cvssMetricV2" ):
87
94
results = {"cvss_version" : "CVSS 2.0" ,
88
95
"cvss_baseScore" : float (metric .get ("cvssData" ).get ("baseScore" )),
89
96
"cvss_severity" : metric .get ("baseSeverity" ),
90
- "cisa_kev" : cisa_kev }
97
+ "cisa_kev" : cisa_kev ,
98
+ "cpe" : cpe }
91
99
return results
92
100
elif unique_cve .get ("cve" ).get ("vulnStatus" ) == "Awaiting Analysis" :
93
101
print (f"{ cve_id :<18} NIST Status: { unique_cve .get ('cve' ).get ('vulnStatus' )} " )
94
102
else :
95
103
print (f"{ cve_id :<18} Not Found in NIST NVD." )
104
+ exit ()
96
105
else :
97
106
print (f"{ cve_id :<18} Error code { nvd_status_code } " )
98
107
except requests .exceptions .ConnectionError :
@@ -113,17 +122,48 @@ def colored_print(priority):
113
122
return colored (priority , 'green' )
114
123
115
124
125
+ # Extract CVE product details
126
+ def parse_cpe (cpe_str ):
127
+ """
128
+ Parses a CPE URI string and extracts the vendor, product, and version.
129
+ Assumes the CPE string is in the format: cpe:/a:vendor:product:version:update:edition:language
130
+ """
131
+ # Splitting the CPE string into components
132
+ parts = cpe_str .split (':' )
133
+
134
+ # Extracting vendor, product, and version
135
+ vendor = parts [3 ] if len (parts ) > 2 else None
136
+ product = parts [4 ] if len (parts ) > 3 else None
137
+
138
+ return vendor , product
139
+
140
+
141
+ # Truncate for printing
142
+ def truncate_string (input_string , max_length ):
143
+ """
144
+ Truncates a string to a maximum length, appending an ellipsis if the string is too long.
145
+ """
146
+ if len (input_string ) > max_length :
147
+ return input_string [:max_length - 3 ] + "..."
148
+ else :
149
+ return input_string
150
+
151
+
116
152
# Function manages the outputs
117
- def print_and_write (working_file , cve_id , priority , epss , cvss_base_score , cvss_version , cvss_severity , cisa_kev , verbose ):
153
+ def print_and_write (working_file , cve_id , priority , epss , cvss_base_score , cvss_version , cvss_severity , cisa_kev ,
154
+ verbose , cpe ):
118
155
119
156
color_priority = colored_print (priority )
157
+ vendor , product = parse_cpe (cpe )
120
158
121
159
if verbose :
122
- print (f"{ cve_id :<18} { color_priority :<22} { epss :<9} { cvss_base_score :<6} { cvss_version :<10} { cvss_severity :<10} { cisa_kev } " )
160
+ print (f"{ cve_id :<18} { color_priority :<22} { epss :<9} { cvss_base_score :<6} { cvss_version :<10} { cvss_severity :<10} "
161
+ f"{ cisa_kev :<10} { truncate_string (vendor ,15 ):<18} { truncate_string (product , 20 )} " )
123
162
else :
124
163
print (f"{ cve_id :<18} { color_priority :<22} " )
125
164
if working_file :
126
- working_file .write (f"{ cve_id } ,{ priority } ,{ epss } ,{ cvss_base_score } ,{ cvss_version } ,{ cvss_severity } ,{ cisa_kev } \n " )
165
+ working_file .write (f"{ cve_id } ,{ priority } ,{ epss } ,{ cvss_base_score } ,{ cvss_version } ,{ cvss_severity } ,"
166
+ f"{ cisa_kev } ,{ cpe } ,{ vendor } ,{ product } \n " )
127
167
128
168
129
169
# Main function
@@ -139,25 +179,25 @@ def worker(cve_id, cvss_score, epss_score, verbose_print, sem, save_output=None)
139
179
if nist_result .get ("cisa_kev" ):
140
180
print_and_write (working_file , cve_id , 'Priority 1+' , epss_result .get ('epss' ),
141
181
nist_result .get ('cvss_baseScore' ), nist_result .get ('cvss_version' ),
142
- nist_result .get ('cvss_severity' ), 'TRUE' , verbose_print )
182
+ nist_result .get ('cvss_severity' ), 'TRUE' , verbose_print , nist_result . get ( 'cpe' ) )
143
183
elif nist_result .get ("cvss_baseScore" ) >= cvss_score :
144
184
if epss_result .get ("epss" ) >= epss_score :
145
185
print_and_write (working_file , cve_id , 'Priority 1' , epss_result .get ('epss' ),
146
186
nist_result .get ('cvss_baseScore' ), nist_result .get ('cvss_version' ),
147
- nist_result .get ('cvss_severity' ), 'FALSE' , verbose_print )
187
+ nist_result .get ('cvss_severity' ), 'FALSE' , verbose_print , nist_result . get ( 'cpe' ) )
148
188
else :
149
189
print_and_write (working_file , cve_id , 'Priority 2' , epss_result .get ('epss' ),
150
190
nist_result .get ('cvss_baseScore' ), nist_result .get ('cvss_version' ),
151
- nist_result .get ('cvss_severity' ), 'FALSE' , verbose_print )
191
+ nist_result .get ('cvss_severity' ), 'FALSE' , verbose_print , nist_result . get ( 'cpe' ) )
152
192
else :
153
193
if epss_result .get ("epss" ) >= epss_score :
154
194
print_and_write (working_file , cve_id , 'Priority 3' , epss_result .get ('epss' ),
155
195
nist_result .get ('cvss_baseScore' ), nist_result .get ('cvss_version' ),
156
- nist_result .get ('cvss_severity' ), 'FALSE' , verbose_print )
196
+ nist_result .get ('cvss_severity' ), 'FALSE' , verbose_print , nist_result . get ( 'cpe' ) )
157
197
else :
158
198
print_and_write (working_file , cve_id , 'Priority 4' , epss_result .get ('epss' ),
159
199
nist_result .get ('cvss_baseScore' ), nist_result .get ('cvss_version' ),
160
- nist_result .get ('cvss_severity' ), 'FALSE' , verbose_print )
200
+ nist_result .get ('cvss_severity' ), 'FALSE' , verbose_print , nist_result . get ( 'cpe' ) )
161
201
except (TypeError , AttributeError ):
162
202
pass
163
203
0 commit comments