|
16 | 16 | from cve_bin_tool.input_engine import TriageData
|
17 | 17 | from cve_bin_tool.log import LOGGER
|
18 | 18 | from cve_bin_tool.theme import cve_theme
|
19 |
| -from cve_bin_tool.util import CVE, CVEData, ProductInfo, VersionInfo |
| 19 | +from cve_bin_tool.util import CVE, CVEData, ProductInfo, Remarks, VersionInfo |
20 | 20 | from cve_bin_tool.version_compare import Version
|
21 | 21 |
|
22 | 22 |
|
@@ -180,8 +180,13 @@ def get_cves(self, product_info: ProductInfo, triage_data: TriageData):
|
180 | 180 | end_excluding=version_end_excluding,
|
181 | 181 | )
|
182 | 182 |
|
183 |
| - # Go through and get all the severities |
| 183 | + product_info_data: CVEData | None = self.all_cve_data.get(product_info) |
| 184 | + prev_cves: List[CVE] = ( |
| 185 | + product_info_data.get("cves", []) if product_info_data is not None else [] # type: ignore |
| 186 | + ) |
184 | 187 | cves: List[CVE] = []
|
| 188 | + |
| 189 | + # Go through and get all the severities |
185 | 190 | if cve_list:
|
186 | 191 | finished = False
|
187 | 192 | max_cves = 500
|
@@ -223,15 +228,26 @@ def get_cves(self, product_info: ProductInfo, triage_data: TriageData):
|
223 | 228 | if duplicate_found:
|
224 | 229 | continue
|
225 | 230 |
|
| 231 | + # Check if we already found this CVE with a previous scan. |
| 232 | + # In that case we need to check where to get our triage info |
| 233 | + # from. |
| 234 | + # TODO: turn the list of CVEs into a set to avoid needing |
| 235 | + # the linear-time lookup. |
| 236 | + prev_cve = next( |
| 237 | + ( |
| 238 | + cve |
| 239 | + for cve in prev_cves |
| 240 | + if cve.cve_number == row["cve_number"] |
| 241 | + ), |
| 242 | + None, |
| 243 | + ) |
| 244 | + |
226 | 245 | triage = triage_data.get(row["cve_number"]) or triage_data.get(
|
227 | 246 | "default"
|
228 | 247 | )
|
229 |
| - # Only scan cves if triage is not None. |
230 |
| - # Triage will only be None if triage_data don't have default attribute. |
231 |
| - # NOTE: Triage can be empty dictionary so checking `if triage:` won't suffice. |
232 |
| - if triage is not None: |
| 248 | + if prev_cve is None: |
233 | 249 | row_dict = dict(row)
|
234 |
| - row_dict.update(triage) |
| 250 | + |
235 | 251 | # print(row_dict)
|
236 | 252 | row_dict["severity"] = row_dict["severity"] or row["severity"]
|
237 | 253 | # Checking for exploits
|
@@ -274,7 +290,39 @@ def get_cves(self, product_info: ProductInfo, triage_data: TriageData):
|
274 | 290 | f'metrics found in CVE {row_dict["cve_number"]} is {row_dict["metric"]}'
|
275 | 291 | )
|
276 | 292 | cve = CVE(**row_dict)
|
277 |
| - cves.append(cve) |
| 293 | + else: |
| 294 | + cve = prev_cve |
| 295 | + |
| 296 | + # We assume that only one source has the triage info. |
| 297 | + # We try to figure out here which one. |
| 298 | + # If we have useful info in the triage data we received, |
| 299 | + # then we use it. |
| 300 | + if triage is not None and ( |
| 301 | + # Either the new cve does not have triage data, |
| 302 | + # or it is trivial (newly found cve) |
| 303 | + not cve.remarks |
| 304 | + or cve.remarks == Remarks.NewFound |
| 305 | + ): |
| 306 | + for key in [ |
| 307 | + "remarks", |
| 308 | + "comments", |
| 309 | + "response", |
| 310 | + "justification", |
| 311 | + "severity", |
| 312 | + ]: |
| 313 | + data = triage.get(key) |
| 314 | + if data: |
| 315 | + if ( |
| 316 | + key == "severity" |
| 317 | + and self.check_exploits |
| 318 | + and row_dict["cve_number"] in self.exploits_list |
| 319 | + ): |
| 320 | + data += "-EXPLOIT" |
| 321 | + |
| 322 | + self.logger.debug(f"Setting field {key} to: {data}") |
| 323 | + cve = cve._replace(**{key: data}) |
| 324 | + |
| 325 | + cves.append(cve) |
278 | 326 |
|
279 | 327 | if cves:
|
280 | 328 | self.products_with_cve += 1
|
|
0 commit comments