@@ -25,6 +25,7 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
2525 test file: https://github.com/DefectDojo/django-DefectDojo/blob/master/unittests/scans/wiz/multiple_findings.csv
2626 """
2727 findings = []
28+
2829 description_fields = [
2930 "Description" ,
3031 "Resource Type" ,
@@ -51,42 +52,34 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
5152 "Kubernetes Cluster" ,
5253 "Kubernetes Namespace" ,
5354 "Container Service" ,
55+ "Provider ID" ,
56+ "Risks" ,
57+ "Threats"
58+ "Created At" ,
59+ "Status Changed At" ,
60+ "Updated At" ,
5461 ]
62+
5563 # Iterate over the objects to create findings
5664 for row in reader :
5765 title = row .get ("Title" )
66+ issue_id = row .get ("Issue ID" )
5867 severity = row .get ("Severity" )
5968 mitigation = row .get ("Remediation Recommendation" )
69+
70+ if row .get ("Resolution" ):
71+ mitigation += "\n Resolution: " + row .get ("Resolution" )
72+
6073 description = ""
6174 status_dict = WizcliParsers .convert_status (row .get ("Status" , None ))
75+ date = parse_wiz_datetime (row , "Created At" )
6276 if status_dict .get ("is_mitigated" , False ):
6377 # If the finding is mitigated, set the date to the mitigation date
6478 mitigated_timestamp = None
6579
6680 if row .get ("Resolved Time" , None ):
67- with contextlib .suppress (ValueError ):
68- mitigated_timestamp = date_parser .parse (row .get ("Resolved Time" ))
69-
70- if not mitigated_timestamp :
71- # other timestamps in the wiz scans are ISO8601
72- # but the Resolved Time is in a different format based on data we've seen
73- # example value: 2025-04-03 20:20:00.43042 +0000 UTC
74-
75- resolved_time_string = row .get ("Resolved Time" )
76- # need to use suppress as try-except ValueError doesn't work here for some reason
77-
78- # File "/usr/local/lib/python3.11/_strptime.py", line 352, in _strptime
79- # raise ValueError("unconverted data remains: %s" %
80- # ValueError: unconverted data remains: CET
81- with contextlib .suppress (ValueError ):
82- mitigated_timestamp = datetime .strptime (
83- resolved_time_string , "%Y-%m-%d %H:%M:%S.%f %z %Z" ,
84- )
85-
86- if not mitigated_timestamp :
87- logger .warning (f"Unable to parse Resolved Time: { resolved_time_string } " )
88-
89- status_dict ["mitigated" ] = mitigated_timestamp
81+ mitigated_timestamp = parse_wiz_datetime (row , "Resolved Time" )
82+ status_dict ["mitigated" ] = mitigated_timestamp or None
9083
9184 # Iterate over the description fields to create the description
9285 for field in description_fields :
@@ -96,10 +89,12 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
9689 findings .append (
9790 Finding (
9891 title = title ,
92+ date = date ,
9993 description = description ,
10094 severity = severity .lower ().capitalize (),
10195 static_finding = False ,
10296 dynamic_finding = True ,
97+ unique_id_from_tool = issue_id ,
10398 mitigation = mitigation ,
10499 test = test ,
105100 ** status_dict ,
@@ -232,3 +227,39 @@ def get_findings(self, filename, test):
232227 return WizParserByDetailedName ().parse_findings (test , reader )
233228 msg = "This CSV format of Wiz is not supported"
234229 raise ValueError (msg )
230+
231+
232+ def parse_wiz_datetime (row : dict , column : str ) -> datetime :
233+ """
234+ Parse the Wiz datetime string to a datetime object.
235+
236+ The format of the date is "2025-04-03 20:20:00.43042 +0000 UTC"
237+ """
238+ value = row .get (column )
239+ if value is None :
240+ return None
241+
242+ parsed_value = None
243+
244+ # Try default parser first
245+ with contextlib .suppress (ValueError ):
246+ parsed_value = date_parser .parse (value )
247+
248+ # other timestamps in the wiz scans are ISO8601
249+ # but the Resolved Time is in a different format based on data we've seen
250+ # example value: 2025-04-03 20:20:00.43042 +0000 UTC
251+
252+ # need to use suppress as try-except ValueError doesn't work here for some reason
253+ # File "/usr/local/lib/python3.11/_strptime.py", line 352, in _strptime
254+ # raise ValueError("unconverted data remains: %s" %
255+ # ValueError: unconverted data remains: CET
256+ if not parsed_value :
257+ with contextlib .suppress (ValueError ):
258+ parsed_value = datetime .strptime (
259+ value , "%Y-%m-%d %H:%M:%S.%f %z %Z" ,
260+ )
261+
262+ if not parsed_value :
263+ logger .warning (f"Unable to parse Resolved Time: { value } " )
264+
265+ return parsed_value
0 commit comments