Skip to content

Commit 4e11e27

Browse files
authored
New Parser: Kiuwan SCA (#10522)
* Update kiuwan docs * Add Kiuwan SCA test files * Add Kiuwan SCA Parser Unittest * Add Kiuwan SCA parser implementation * Add more fields to the Kiuwan SCA parser * Update parser docs * Add test case for "muted" findings * Update finding title * Minor cleanupo * Update hashing logic * Remove print statement * Add optional epss support * Add epss unit test * Add custom deduplication logic as default static is not enough for SCA * Remove cve as it is not allowed for deduplication * Set finding title to component name as this makes more sense within the UI display * Fix lint warnings * Fix another lint warning * Fix lint error * fix lint errors * fix lint errors * fix lint errors * Fix lint * Fix lint * Refactor: minor cleanup * chore: add sha256sum of settings.dist.py * chore: add sha256sum of settings.dist.py
1 parent a55a8cc commit 4e11e27

10 files changed

Lines changed: 991 additions & 4 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
title: Kiuwan Scanner (SCA i.e. "Insights")
3+
toc_hide: true
4+
---
5+
Import Kiuwan Insights Scan in JSON format. Export via API endpoint `insights/analysis/security` as json and create a file for importing to DefectDojo.
6+
7+
### Example Code
8+
9+
Data can be fetched from the [Kiuwan REST API](https://static.kiuwan.com/rest-api/kiuwan-rest-api.html) like this:
10+
11+
```
12+
import requests, json
13+
headers = {'Authorization': 'Basic $KIUWAN_TOKEN', 'Accept' : 'application/json'}
14+
15+
appName = "Test"
16+
analysisCode = "A-111-1111111111"
17+
18+
URL = "https://api.kiuwan.com/insights/analysis/security?analysisCode=" + analysisCode + "&application=" + appName
19+
response = requests.get(url = URL, headers = headers)
20+
jsonResponse = r.json()
21+
data = jsonResponse["data"]
22+
saveFile("result.json", json.dumps(data, indent=2))
23+
```
24+
25+
### Sample Scan Data
26+
Sample Kiuwan Scanner scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/kiuwan-sca).
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
2-
title: "Kiuwan Scanner"
2+
title: "Kiuwan Scanner (SAST)"
33
toc_hide: true
44
---
5-
Import Kiuwan Scan in CSV format. Export as CSV Results on Kiuwan.
5+
Import Kiuwan SAST Scan in CSV format. Export as CSV Results on Kiuwan, or via the [Kiuwan REST API](https://static.kiuwan.com/rest-api/kiuwan-rest-api.html) endpoint `vulnerabilities/export` (type=csv).
66

77
### Sample Scan Data
8-
Sample Kiuwan Scanner scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/kiuwan).
8+
Sample Kiuwan Scanner scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/kiuwan).
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
a955e77c0c9e292e3d80eec500a586e2c0b43efded3ba74a7fc1801862150e51
1+
2938ce5637b436fb25afc49dbc5eb68e3b640b87e311d052810ca82ad9c641a1

dojo/settings/settings.dist.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,7 @@ def saml2_attrib_map_format(dict):
12701270
"Nancy Scan": ["title", "vuln_id_from_tool"],
12711271
"Wiz Scan": ["title", "description", "severity"],
12721272
"Kubescape JSON Importer": ["title", "component_name"],
1273+
"Kiuwan SCA Scan": ["description", "severity", "component_name", "component_version", "cwe"],
12731274
}
12741275

12751276
# Override the hardcoded settings here via the env var
@@ -1489,6 +1490,7 @@ def saml2_attrib_map_format(dict):
14891490
"Wiz Scan": DEDUPE_ALGO_HASH_CODE,
14901491
"Deepfence Threatmapper Report": DEDUPE_ALGO_HASH_CODE,
14911492
"Kubescape JSON Importer": DEDUPE_ALGO_HASH_CODE,
1493+
"Kiuwan SCA Scan": DEDUPE_ALGO_HASH_CODE,
14921494
}
14931495

14941496
# Override the hardcoded settings here via the env var

dojo/tools/kiuwan_sca/__init__.py

Whitespace-only changes.

dojo/tools/kiuwan_sca/parser.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import hashlib
2+
import json
3+
4+
from dojo.models import Finding
5+
6+
__author__ = "mwager"
7+
8+
9+
class KiuwanSCAParser:
10+
SEVERITY = {
11+
"-": "Low",
12+
"LOW": "Low",
13+
"MEDIUM": "Medium",
14+
"HIGH": "High",
15+
"CRITICAL": "Critical",
16+
"Low": "Low",
17+
"Medium": "Medium",
18+
"High": "High",
19+
"Critical": "Critical",
20+
}
21+
22+
def get_scan_types(self):
23+
return ["Kiuwan SCA Scan"]
24+
25+
def get_label_for_scan_types(self, scan_type):
26+
return scan_type
27+
28+
def get_description_for_scan_types(self, scan_type):
29+
return "Import Kiuwan Insights Scan in JSON format. Export as JSON using Kiuwan REST API."
30+
31+
def get_findings(self, filename, test):
32+
data = json.load(filename)
33+
dupes = {}
34+
35+
for row in data:
36+
# if a finding was "muted" in the Kiuwan UI, we ignore it (e.g. marked as false positive)
37+
if row["muted"] is True:
38+
continue
39+
40+
finding = Finding(test=test)
41+
finding.unique_id_from_tool = row["id"]
42+
finding.cve = row["cve"]
43+
finding.description = row["description"]
44+
finding.severity = self.SEVERITY[row["securityRisk"]]
45+
46+
if "components" in row and len(row["components"]) > 0:
47+
finding.component_name = row["components"][0]["artifact"]
48+
finding.component_version = row["components"][0]["version"]
49+
finding.title = finding.component_name + " v" + str(finding.component_version)
50+
51+
if not finding.title:
52+
finding.title = row["cve"]
53+
54+
if "cwe" in row and "CWE-" in row["cwe"]:
55+
finding.cwe = int(row["cwe"].replace("CWE-", ""))
56+
57+
if "epss_score" in row:
58+
finding.epss_score = row["epss_score"]
59+
if "epss_percentile" in row:
60+
finding.epss_percentile = row["epss_percentile"]
61+
62+
if "cVSSv3BaseScore" in row:
63+
finding.cvssv3_score = float(row["cVSSv3BaseScore"])
64+
65+
finding.references = "See Kiuwan Web UI"
66+
finding.mitigation = "See Kiuwan Web UI"
67+
finding.static_finding = True
68+
69+
key = hashlib.sha256(
70+
(
71+
finding.description
72+
+ "|"
73+
+ finding.severity
74+
+ "|"
75+
+ finding.component_name
76+
+ "|"
77+
+ finding.component_version
78+
+ "|"
79+
+ str(finding.cwe)
80+
).encode("utf-8"),
81+
).hexdigest()
82+
83+
if key not in dupes:
84+
dupes[key] = finding
85+
86+
return list(dupes.values())

0 commit comments

Comments
 (0)