Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions dojo/tools/aqua/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,32 +115,32 @@ def get_findings(self, json_output, test):
elif "result" in tree: # Aqua Scan Report from apiv2
resulttree = tree["result"]
for vuln in resulttree:
resource = vuln.get("resource")
resource = vuln.get("resource") or {}
item = self.get_item(resource, vuln, test)
unique_key = resource.get("cpe") + vuln.get("name", "None") + resource.get("path", "None")
unique_key = (resource.get("cpe") or "") + (vuln.get("name") or "") + (resource.get("path") or "")
self.items[unique_key] = item
elif "cves" in tree: # Aqua Scan Report from apiv1
for cve in tree["cves"]:
unique_key = cve.get("file") + cve.get("name")
unique_key = (cve.get("file") or "") + (cve.get("name") or "")
self.items[unique_key] = self.get_item_v2(cve, test)
return list(self.items.values())

def vulnerability_tree(self, vulnerabilitytree, test):
for node in vulnerabilitytree:
resource = node.get("resource")
resource = node.get("resource") or {}
vulnerabilities = node.get("vulnerabilities", [])
sensitive_items = resource.get("sensitive_items", [])
if vulnerabilities is None:
vulnerabilities = []
for vuln in vulnerabilities:
item = self.get_item(resource, vuln, test)
unique_key = resource.get("cpe") + vuln.get("name", "None") + resource.get("path", "None")
unique_key = (resource.get("cpe") or "") + (vuln.get("name") or "") + (resource.get("path") or "")
self.items[unique_key] = item
if sensitive_items is None:
sensitive_items = []
for sensitive_item in sensitive_items:
item = self.get_item_sensitive_data(resource, sensitive_item, test)
unique_key = resource.get("cpe") + resource.get("path", "None") + str(sensitive_item)
unique_key = (resource.get("cpe") or "") + (resource.get("path") or "") + str(sensitive_item)
self.items[unique_key] = item

def get_item(self, resource, vuln, test):
Expand Down Expand Up @@ -297,6 +297,8 @@ def get_item_sensitive_data(self, resource, sensitive_item, test):
return finding

def severity_of(self, score):
if score is None:
return "Info"
if isinstance(score, str):
if score == "high":
return "High"
Expand Down
13 changes: 7 additions & 6 deletions dojo/tools/snyk/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,21 +246,22 @@ def get_item(self, vulnerability, test, target_file=None, upgrades=None, image=N

# manage CVE and CWE with idnitifiers
cwe_references = ""
if "identifiers" in vulnerability:
if "CVE" in vulnerability["identifiers"]:
vulnerability_ids = vulnerability["identifiers"]["CVE"]
identifiers = vulnerability.get("identifiers") or {}
if identifiers:
if "CVE" in identifiers:
vulnerability_ids = identifiers["CVE"]
if vulnerability_ids:
finding.unsaved_vulnerability_ids = vulnerability_ids

if "CWE" in vulnerability["identifiers"]:
cwes = vulnerability["identifiers"]["CWE"]
if "CWE" in identifiers:
cwes = identifiers["CWE"]
if cwes:
# Per the current json format, if several CWEs, take the
# first one.
finding.cwe = int(cwes[0].split("-")[1])
# Persist the full list of CWEs via the Finding_CWE relation
finding.unsaved_cwes = [int(c.split("-")[1]) for c in cwes]
if len(vulnerability["identifiers"]["CWE"]) > 1:
if len(identifiers["CWE"]) > 1:
cwe_references = ", ".join(cwes)
else:
finding.cwe = 1035
Expand Down
16 changes: 16 additions & 0 deletions unittests/scans/aqua/api_v1_missing_fields.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"cves": [
{
"name": "CVE-2023-0003",
"score": 8.1,
"description": "Test finding with missing file field",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-0003"
},
{
"file": "/usr/lib/libssl.so",
"name": null,
"score": 6.5,
"description": "Test finding with null name field"
}
]
}
23 changes: 23 additions & 0 deletions unittests/scans/aqua/api_v2_missing_fields.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"result": [
{
"name": "CVE-2023-0001",
"description": "Test vulnerability without resource object",
"nvd_severity": "high",
"nvd_cvss3_score": 7.5,
"resource": null
},
{
"name": "CVE-2023-0002",
"description": "Test vulnerability with resource missing cpe",
"nvd_severity": "medium",
"nvd_cvss3_score": 5.0,
"resource": {
"format": "apk",
"name": "libcrypto",
"version": "1.0.2",
"path": "/usr/lib/libcrypto.so"
}
}
]
}
28 changes: 28 additions & 0 deletions unittests/scans/aqua/cicd_missing_resource_fields.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"resources": [
{
"resource": null,
"vulnerabilities": [
{
"name": "CVE-2023-0004",
"description": "Vuln on a node with null resource",
"nvd_score": 7.0
}
]
},
{
"resource": {
"format": "apk",
"name": "busybox",
"version": "1.30.1"
},
"vulnerabilities": [
{
"name": "CVE-2023-0005",
"description": "Vuln on a resource missing cpe and path",
"nvd_score": 5.5
}
]
}
]
}
41 changes: 41 additions & 0 deletions unittests/scans/snyk/single_project_null_identifiers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"vulnerabilities": [
{
"id": "SNYK-TEST-0001",
"title": "Test Null Identifiers",
"packageName": "test-package",
"version": "1.0.0",
"severity": "high",
"cvssScore": 7.5,
"semver": {
"vulnerable": [
"<2.0.0"
]
},
"from": [
"my-project@1.0.0",
"test-package@1.0.0"
],
"identifiers": null,
"description": "Finding with null identifiers field"
},
{
"id": "SNYK-TEST-0002",
"title": "Test Empty Identifiers",
"packageName": "another-package",
"version": "3.2.1",
"severity": "medium",
"cvssScore": 5.0,
"semver": {
"vulnerable": ">=1.0.0 <4.0.0"
},
"from": [
"my-project@1.0.0",
"another-package@3.2.1"
],
"identifiers": {},
"description": "Finding with empty identifiers object"
}
],
"packageManager": "npm"
}
19 changes: 19 additions & 0 deletions unittests/tools/test_aqua_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,22 @@ def test_aqua_parser_over_api_v2_empty(self):
parser = AquaParser()
findings = parser.get_findings(testfile, Test())
self.assertEqual(0, len(findings))

def test_aqua_parser_api_v2_with_missing_fields(self):
with (get_unit_tests_scans_path("aqua") / "api_v2_missing_fields.json").open(encoding="utf-8") as testfile:
parser = AquaParser()
findings = parser.get_findings(testfile, Test())
# First result has null resource, second is missing cpe
self.assertEqual(2, len(findings))

def test_aqua_parser_api_v1_with_missing_fields(self):
with (get_unit_tests_scans_path("aqua") / "api_v1_missing_fields.json").open(encoding="utf-8") as testfile:
parser = AquaParser()
findings = parser.get_findings(testfile, Test())
self.assertEqual(2, len(findings))

def test_aqua_parser_cicd_with_missing_resource_fields(self):
with (get_unit_tests_scans_path("aqua") / "cicd_missing_resource_fields.json").open(encoding="utf-8") as testfile:
parser = AquaParser()
findings = parser.get_findings(testfile, Test())
self.assertEqual(2, len(findings))
10 changes: 10 additions & 0 deletions unittests/tools/test_snyk_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,16 @@ def test_snykcode_issue_9270_epss(self):
findings[0].title,
)

def test_snykParser_null_identifiers(self):
with (get_unit_tests_scans_path("snyk") / "single_project_null_identifiers.json").open(encoding="utf-8") as testfile:
parser = SnykParser()
findings = parser.get_findings(testfile, Test())
self.assertEqual(2, len(findings))
# First finding has null identifiers — no CVE/CWE should be extracted
self.assertFalse(getattr(findings[0], "unsaved_vulnerability_ids", []))
# Second finding has empty identifiers — same result
self.assertFalse(getattr(findings[1], "unsaved_vulnerability_ids", []))


class TestSnykParserImageLocations(DojoTestCase):
@skip_unless_v3
Expand Down
Loading