1
1
from typing import List , Set , Optional , Any , get_args
2
2
from enum import Enum , auto
3
+ import uuid
4
+
3
5
from pydantic import BaseModel , Field , PrivateAttr
4
6
from data .Solution import Solution
5
- from data .Categories import Category , TechnologyStack , SecurityAspect , SeverityLevel , RemediationType , \
6
- AffectedComponent , Compliance , Environment
7
+ from data .Categories import (
8
+ Category ,
9
+ TechnologyStack ,
10
+ SecurityAspect ,
11
+ SeverityLevel ,
12
+ RemediationType ,
13
+ AffectedComponent ,
14
+ Compliance ,
15
+ Environment ,
16
+ )
7
17
import json
8
18
9
19
import logging
12
22
13
23
14
24
class Finding (BaseModel ):
25
+ id : str = Field (default_factory = lambda : f"{ str (uuid .uuid4 ())} " )
15
26
title : List [str ] = Field (default_factory = list )
16
27
source : Set [str ] = Field (default_factory = set )
17
28
descriptions : List [str ] = Field (default_factory = list )
@@ -21,7 +32,7 @@ class Finding(BaseModel):
21
32
severity : Optional [int ] = None
22
33
priority : Optional [int ] = None
23
34
location_list : List [str ] = Field (default_factory = list )
24
- category : Category = None
35
+ category : Optional [ Category ] = None
25
36
unsupervised_cluster : Optional [int ] = None
26
37
solution : Optional ["Solution" ] = None
27
38
_llm_service : Optional [Any ] = PrivateAttr (default = None )
@@ -35,7 +46,9 @@ def combine_descriptions(self) -> "Finding":
35
46
logger .error ("LLM Service not set, cannot combine descriptions." )
36
47
return self
37
48
38
- self .description = self .llm_service .combine_descriptions (self .descriptions , self .cve_ids , self .cwe_ids )
49
+ self .description = self .llm_service .combine_descriptions (
50
+ self .descriptions , self .cve_ids , self .cwe_ids
51
+ )
39
52
return self
40
53
41
54
def add_category (self ) -> "Finding" :
@@ -47,34 +60,45 @@ def add_category(self) -> "Finding":
47
60
48
61
# Classify technology stack
49
62
technology_stack_options = list (TechnologyStack )
50
- self .category .technology_stack = self .llm_service .classify_kind (self , "technology_stack" ,
51
- technology_stack_options )
63
+ self .category .technology_stack = self .llm_service .classify_kind (
64
+ self , "technology_stack" , technology_stack_options
65
+ )
52
66
53
67
# Classify security aspect
54
68
security_aspect_options = list (SecurityAspect )
55
- self .category .security_aspect = self .llm_service .classify_kind (self , "security_aspect" , security_aspect_options )
69
+ self .category .security_aspect = self .llm_service .classify_kind (
70
+ self , "security_aspect" , security_aspect_options
71
+ )
56
72
57
73
# Classify severity level
58
74
severity_level_options = list (SeverityLevel )
59
- self .category .severity_level = self .llm_service .classify_kind (self , "severity_level" , severity_level_options )
75
+ self .category .severity_level = self .llm_service .classify_kind (
76
+ self , "severity_level" , severity_level_options
77
+ )
60
78
61
79
# Classify remediation type
62
80
remediation_type_options = list (RemediationType )
63
- self .category .remediation_type = self .llm_service .classify_kind (self , "remediation_type" ,
64
- remediation_type_options )
81
+ self .category .remediation_type = self .llm_service .classify_kind (
82
+ self , "remediation_type" , remediation_type_options
83
+ )
65
84
66
85
# Classify affected component
67
86
affected_component_options = list (AffectedComponent )
68
- self .category .affected_component = self .llm_service .classify_kind (self , "affected_component" ,
69
- affected_component_options )
87
+ self .category .affected_component = self .llm_service .classify_kind (
88
+ self , "affected_component" , affected_component_options
89
+ )
70
90
71
91
# Classify compliance
72
92
compliance_options = list (Compliance )
73
- self .category .compliance = self .llm_service .classify_kind (self , "compliance" , compliance_options )
93
+ self .category .compliance = self .llm_service .classify_kind (
94
+ self , "compliance" , compliance_options
95
+ )
74
96
75
97
# Classify environment
76
98
environment_options = list (Environment )
77
- self .category .environment = self .llm_service .classify_kind (self , "environment" , environment_options )
99
+ self .category .environment = self .llm_service .classify_kind (
100
+ self , "environment" , environment_options
101
+ )
78
102
79
103
return self
80
104
@@ -213,17 +237,19 @@ def to_html(self, table=False):
213
237
result += "<tr><th>Name</th><th>Value</th></tr>"
214
238
result += f"<tr><td>Title</td><td>{ ', ' .join (self .title )} </td></tr>"
215
239
result += f"<tr><td>Source</td><td>{ ', ' .join (self .source )} </td></tr>"
216
- result += (
217
- f"<tr><td>Description</td><td>{ self .description } </td></tr>"
218
- )
240
+ result += f"<tr><td>Description</td><td>{ self .description } </td></tr>"
219
241
if len (self .location_list ) > 0 :
220
242
result += f"<tr><td>Location List</td><td>{ ' & ' .join (map (str , self .location_list ))} </td></tr>"
221
243
result += f"<tr><td>CWE IDs</td><td>{ ', ' .join (self .cwe_ids )} </td></tr>"
222
244
result += f"<tr><td>CVE IDs</td><td>{ ', ' .join (self .cve_ids )} </td></tr>"
223
245
result += f"<tr><td>Severity</td><td>{ self .severity } </td></tr>"
224
246
result += f"<tr><td>Priority</td><td>{ self .priority } </td></tr>"
225
247
if self .category is not None :
226
- result += '<tr><td>Category</td><td>' + str (self .category ).replace ("\n " , "<br />" ) + '</td></tr>'
248
+ result += (
249
+ "<tr><td>Category</td><td>"
250
+ + str (self .category ).replace ("\n " , "<br />" )
251
+ + "</td></tr>"
252
+ )
227
253
if self .unsupervised_cluster is not None :
228
254
result += f"<tr><td>Unsupervised Cluster</td><td>{ self .unsupervised_cluster } </td></tr>"
229
255
result += "</table>"
0 commit comments