Skip to content

Commit 71d6761

Browse files
sysdig: support new json format
1 parent 16e9001 commit 71d6761

5 files changed

Lines changed: 117 additions & 3105 deletions

File tree

docs/content/en/connecting_your_tools/parsers/file/sysdig_reports.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
title: "Sysdig Vulnerability Reports"
33
toc_hide: true
44
---
5+
Legacy Scanning Engine:
6+
57
Import CSV report files from Sysdig or a Sysdig UI JSON Report
68
Parser will accept Pipeline, Registry and Runtime reports created from the UI
7-
89
More information available at [our reporting docs page](https://docs.sysdig.com/en/docs/sysdig-secure/vulnerabilities/reporting)
910

11+
Vulnerability Management Engine:
12+
Import CSV and JSON files creared by Sysdig CLI scanner.
13+
14+
1015
### Sample Scan Data
1116
Sample Sysdig Vulnerability Reports scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/sysdig_reports).

dojo/tools/sysdig_reports/parser.py

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def get_label_for_scan_types(self, scan_type):
1818
return "Sysdig Vulnerability Report Scan"
1919

2020
def get_description_for_scan_types(self, scan_type):
21-
return "Legacy scanner: Import of Sysdig Pipeline, Registry and Runtime Vulnerability Report Scans in CSV format or a Sysdig UI JSON Report"
21+
return "Import of Sysdig Pipeline, Registry and Runtime Vulnerability Report Scans in CSV format or a Sysdig UI JSON Report"
2222

2323
def get_findings(self, filename, test):
2424
if filename is None:
@@ -32,10 +32,18 @@ def get_findings(self, filename, test):
3232
data = json.loads(str(scan_data, "utf-8"))
3333
except Exception:
3434
data = json.loads(scan_data)
35-
return self.parse_json(data=data, test=test)
35+
36+
if "data" in data:
37+
return self.parse_json_legacy(data=data, test=test)
38+
39+
if "result" in data:
40+
return self.parse_json(data=data, test=test)
41+
42+
msg = "JSON file is not in the expected format, expected data element or result element"
43+
raise ValueError(msg)
3644
return ()
3745

38-
def parse_json(self, data, test):
46+
def parse_json_legacy(self, data, test):
3947
vulnerability = data.get("data", None)
4048
if not vulnerability:
4149
return []
@@ -66,6 +74,7 @@ def parse_json(self, data, test):
6674
packageVersion = item.get("packageVersion", "")
6775
packageSuggestedFix = item.get("packageSuggestedFix", "")
6876
k8sPodCount = item.get("k8sPodCount", "")
77+
6978
description = ""
7079
description += "imageId: " + imageId + "\n"
7180
description += "imagePullString: " + imagePullString + "\n"
@@ -87,9 +96,12 @@ def parse_json(self, data, test):
8796
description += "packageVersion: " + packageVersion + "\n"
8897
description += "packageSuggestedFix: " + packageSuggestedFix + "\n"
8998
description += "k8sPodCount: " + str(k8sPodCount) + "\n"
99+
90100
mitigation = ""
91101
mitigation += "vulnFixAvailable: " + str(vulnFixAvailable) + "\n"
92102
mitigation += "vulnFixVersion: " + vulnFixVersion + "\n"
103+
mitigation += "suggestedFix: " + packageSuggestedFix + "\n"
104+
93105
find = Finding(
94106
title=vulnName + "_" + vulnFixVersion,
95107
test=test,
@@ -107,6 +119,79 @@ def parse_json(self, data, test):
107119
findings.append(find)
108120
return findings
109121

122+
def parse_json(self, data, test):
123+
findings = []
124+
packages = data.get("result", {}).get("packages", [])
125+
126+
for package in packages:
127+
# print(package)
128+
packageName = package.get("name", "")
129+
packageType = package.get("type", "")
130+
packagePath = package.get("path", "")
131+
packageVersion = package.get("version", "")
132+
packageSuggestedFix = package.get("suggestedFix", "")
133+
layerDigest = package.get("layerDigest", "")
134+
135+
vulns = package.get("vulns", [])
136+
# print("vulns: %s" % vulns)
137+
for item in vulns:
138+
# print("item: %s" % item)
139+
vulnName = item.get("name", "")
140+
vulnSeverity = item.get("severity", {}).get("value", "")
141+
vulnCvssScore = item.get("cvssScore", {}).get("value", {}).get("score", "")
142+
vulnCvssVersion = item.get("cvssScore", {}).get("value", {}).get("version", "")
143+
vulnCvssVector = item.get("cvssScore", {}).get("value", {}).get("vector", "")
144+
vulnDisclosureDate = item.get("disclosureDate", "")
145+
vulnSolutionDate = item.get("solutionDate", "")
146+
vulnPublishedByVendorDate = item.get("publishDateByVendor", {}).get("nvd", "")
147+
vulnExploitable = item.get("exploitable", "")
148+
vulnFixVersion = item.get("fixedInVersion", "")
149+
150+
description = ""
151+
description += "vulnCvssVersion: " + vulnCvssVersion + "\n"
152+
description += "vulnCvssScore: " + str(vulnCvssScore) + "\n"
153+
description += "vulnCvssVector: " + vulnCvssVector + "\n"
154+
description += "vulnDisclosureDate: " + vulnDisclosureDate + "\n"
155+
description += "vulnPublishedByVendorDate: " + vulnPublishedByVendorDate + "\n"
156+
description += "vulnSolutionDate: " + vulnSolutionDate + "\n"
157+
description += "vulnExploitable: " + str(vulnExploitable) + "\n"
158+
description += "packageName: " + packageName + "\n"
159+
description += "packageType: " + packageType + "\n"
160+
description += "packagePath: " + packagePath + "\n"
161+
description += "packageVersion: " + packageVersion + "\n"
162+
description += "packageSuggestedFix: " + packageSuggestedFix + "\n"
163+
description += "layerDigest: " + layerDigest + "\n"
164+
165+
mitigation = ""
166+
mitigation += "vulnFixVersion: " + vulnFixVersion + "\n"
167+
mitigation += "suggestedFix: " + packageSuggestedFix + "\n"
168+
169+
finding = Finding(
170+
title=vulnName + " - " + packageName + " - " + vulnFixVersion,
171+
test=test,
172+
description=description,
173+
severity=vulnSeverity,
174+
mitigation=mitigation,
175+
static_finding=True,
176+
component_name=packageName,
177+
component_version=packageVersion,
178+
)
179+
180+
try:
181+
if float(vulnCvssVersion) >= 3 and float(vulnCvssVersion) < 4:
182+
finding.cvssv3_score = vulnCvssScore
183+
vectors = cvss.parser.parse_cvss_from_text(vulnCvssVector)
184+
if len(vectors) > 0 and isinstance(vectors[0], CVSS3):
185+
finding.cvss = vectors[0].clean_vector()
186+
except ValueError:
187+
continue
188+
189+
if vulnName != "":
190+
finding.unsaved_vulnerability_ids = []
191+
finding.unsaved_vulnerability_ids.append(vulnName)
192+
findings.append(finding)
193+
return findings
194+
110195
def parse_csv(self, arr_data, test):
111196
if len(arr_data) == 0:
112197
return ()
@@ -203,8 +288,8 @@ def parse_csv(self, arr_data, test):
203288
finding.description += f"\n - **Registry Name:** {row.registry_name}"
204289
finding.description += f"\n - **Registy Image Repository:** {row.registry_image_repository}"
205290
try:
206-
if float(row.cvss_version) >= 3:
207-
finding.cvssv3_score = row.cvss_score
291+
if float(row.cvss_version) >= 3 and float(row.cvss_version) < 4:
292+
finding.cvssv3_score = float(row.cvss_score)
208293
vectors = cvss.parser.parse_cvss_from_text(row.cvss_vector)
209294
if len(vectors) > 0 and isinstance(vectors[0], CVSS3):
210295
finding.cvss = vectors[0].clean_vector()
@@ -219,3 +304,5 @@ def parse_csv(self, arr_data, test):
219304
# finally, Add finding to list
220305
sysdig_report_findings.append(finding)
221306
return sysdig_report_findings
307+
308+

dojo/tools/sysdig_reports/sysdig_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,4 @@ def __init__(self):
5757
self.cloud_provider_name: str = ""
5858
self.cloud_provider_account_id: str = ""
5959
self.cloud_provider_region: str = ""
60-
self.epss_score: float = 0
60+
self.epss_score: float = None

0 commit comments

Comments
 (0)