5
5
import shelve
6
6
import time
7
7
from typing import Annotated , Any , Union , TYPE_CHECKING
8
- from pydantic import BaseModel ,Field
8
+ from pydantic import BaseModel ,Field , computed_field
9
9
from decimal import Decimal
10
10
from requests .exceptions import ReadTimeout
11
11
@@ -21,25 +21,14 @@ class CveEnrichmentObj(BaseModel):
21
21
id :Annotated [str , "^CVE-[1|2][0-9]{3}-[0-9]+$" ]
22
22
cvss :Annotated [Decimal , Field (ge = .1 , le = 10 , decimal_places = 1 )]
23
23
summary :str
24
+
25
+ @computed_field
26
+ @property
27
+ def url (self )-> str :
28
+ BASE_NVD_URL = "https://nvd.nist.gov/vuln/detail/"
29
+ return f"{ BASE_NVD_URL } { self .id } "
24
30
25
31
26
- @staticmethod
27
- def buildEnrichmentOnFailure (id :Annotated [str , "^CVE-[1|2][0-9]{3}-[0-9]+$" ], errorMessage :str ,
28
- raise_exception_on_failure :bool = True )-> CveEnrichmentObj :
29
- if raise_exception_on_failure :
30
- raise Exception (errorMessage )
31
- message = f"{ errorMessage } . Default CVSS of 5.0 used"
32
- print (message )
33
- return CveEnrichmentObj (id = id , cvss = Decimal (5.0 ), summary = message )
34
-
35
-
36
- # We need a MUCH better way to handle issues with the cve.circl.lu API.
37
- # It is often extremely slow or down, which means that we cannot enrich CVEs.
38
- # Downloading the entire database is VERY large, but I don't know that there
39
- # is an alternative.
40
- # Being able to include CVEs that have not made it into this database, or additonal
41
- # enriching comments on pre-existing CVEs, would also be extremely useful.
42
- timeout_error = False
43
32
class CveEnrichment (BaseModel ):
44
33
use_enrichment : bool = True
45
34
cve_api_obj : Union [CVESearch ,None ] = None
@@ -52,8 +41,10 @@ class Config:
52
41
53
42
54
43
@staticmethod
55
- def getCveEnrichment (config :validate , timeout_seconds :int = 10 )-> CveEnrichment :
56
-
44
+ def getCveEnrichment (config :validate , timeout_seconds :int = 10 , force_disable_enrichment :bool = True )-> CveEnrichment :
45
+ if force_disable_enrichment :
46
+ return CveEnrichment (use_enrichment = False , cve_api_obj = None )
47
+
57
48
if config .enrichments :
58
49
try :
59
50
cve_api_obj = CVESearch (CVESSEARCH_API_URL , timeout = timeout_seconds )
@@ -64,34 +55,11 @@ def getCveEnrichment(config:validate, timeout_seconds:int=10)->CveEnrichment:
64
55
return CveEnrichment (use_enrichment = False , cve_api_obj = None )
65
56
66
57
67
- @functools .cache
68
58
def enrich_cve (self , cve_id :str , raise_exception_on_failure :bool = True )-> Union [CveEnrichmentObj ,None ]:
69
- global timeout_error
70
59
71
60
if not self .use_enrichment :
72
- return None
73
-
74
- if timeout_error :
75
- message = f"Previous timeout during enrichment - CVE { cve_id } enrichment skipped."
76
- return CveEnrichmentObj .buildEnrichmentOnFailure (id = cve_id , errorMessage = f"WARNING, { message } " ,
77
- raise_exception_on_failure = raise_exception_on_failure )
78
-
79
- cve_enriched :dict [str ,Any ] = dict ()
80
-
81
- try :
82
- result = self .cve_api_obj .id (cve_id )
83
- cve_enriched ['id' ] = cve_id
84
- cve_enriched ['cvss' ] = result ['cvss' ]
85
- cve_enriched ['summary' ] = result ['summary' ]
86
- return CveEnrichmentObj .model_validate (cve_enriched )
87
- except ReadTimeout as e :
88
- message = f"Timeout enriching CVE { cve_id } : { str (e )} after { self .cve_api_obj .timeout } seconds." \
89
- f" All other CVE Enrichment has been disabled"
90
- #Set a global value to true so future runs don't waste time on this
91
- timeout_error = True
92
- return CveEnrichmentObj .buildEnrichmentOnFailure (id = cve_id , errorMessage = f"ERROR, { message } " ,
93
- raise_exception_on_failure = raise_exception_on_failure )
94
- except Exception as e :
95
- message = f"Error enriching CVE { cve_id } . Are you positive this CVE exists: { str (e )} "
96
- return CveEnrichmentObj .buildEnrichmentOnFailure (id = cve_id , errorMessage = f"WARNING, { message } " ,
97
- raise_exception_on_failure = raise_exception_on_failure )
61
+ CveEnrichmentObj (id = cve_id ,cvss = Decimal (5.0 ),summary = "SUMMARY NOT AVAILABLE! ONLY THE LINK WILL BE USED AT THIS TIME" )
62
+ else :
63
+ print ("WARNING - Dynamic enrichment not supported at this time." )
64
+ CveEnrichmentObj (id = cve_id ,cvss = Decimal (5.0 ),summary = "SUMMARY NOT AVAILABLE! ONLY THE LINK WILL BE USED AT THIS TIME" )
65
+ # Depending on needs, we may add dynamic enrichment functionality back to the tool
0 commit comments