Skip to content

Commit

Permalink
Wiz parser: Import findings regardless of status (#11585)
Browse files Browse the repository at this point in the history
* wiz: support more statuses

* linting
  • Loading branch information
valentijnscholten authored Jan 23, 2025
1 parent 5b01bdd commit ef49dac
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 40 deletions.
61 changes: 25 additions & 36 deletions dojo/tools/wiz/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from dateutil import parser as date_parser

from dojo.models import SEVERITIES, Finding, Test
from dojo.tools.wizcli_common_parsers.parsers import WizcliParsers

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -51,27 +52,28 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
]
# Iterate over the objects to create findings
for row in reader:
if row.get("Status").lower() == "open":
title = row.get("Title")
severity = row.get("Severity")
mitigation = row.get("Remediation Recommendation")
description = ""
# Iterate over the description fields to create the description
for field in description_fields:
if (field_value := row.get(field)) is not None and len(field_value) > 0:
description += f"**{field}**: {field_value}\n"
# Create the finding object
findings.append(
Finding(
title=title,
description=description,
severity=severity.lower().capitalize(),
static_finding=False,
dynamic_finding=True,
mitigation=mitigation,
test=test,
),
)
title = row.get("Title")
severity = row.get("Severity")
mitigation = row.get("Remediation Recommendation")
description = ""
status_dict = WizcliParsers.convert_status(row.get("Status", None))
# Iterate over the description fields to create the description
for field in description_fields:
if (field_value := row.get(field)) is not None and len(field_value) > 0:
description += f"**{field}**: {field_value}\n"
# Create the finding object
findings.append(
Finding(
title=title,
description=description,
severity=severity.lower().capitalize(),
static_finding=False,
dynamic_finding=True,
mitigation=mitigation,
test=test,
**status_dict,
),
)
return findings


Expand Down Expand Up @@ -126,7 +128,7 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:

description = self._construct_string_field(description_fields, row)
mitigation = self._construct_string_field(mitigation_fields, row)
status_dict = self._convert_status(row)
status_dict = WizcliParsers.convert_status(row.get("FindingStatus", None))
# Create the finding object
finding = Finding(
title=f"{package_name}: {vulnerability_id}",
Expand Down Expand Up @@ -156,7 +158,7 @@ def _construct_string_field(self, fields: dict[str, str], row: dict) -> str:

def _parse_tags(self, tags: str) -> list[str]:
"""
parse the Tag string dict, and convert to a list of strings.
Parse the Tag string dict, and convert to a list of strings.
The format of the tags is is "{""key"":""value""}" format
"""
Expand All @@ -172,19 +174,6 @@ def _validate_severities(self, severity: str) -> str:
return "Info"
return severity

def _convert_status(self, row: dict) -> dict:
"""
Convert the "FindingStatus" column to a dict of Finding statuses.
- Open-> Active = True
- Other statuses that may exist...
"""
if (status := row.get("FindingStatus")) is not None:
if status == "Open":
return {"active": True}
# Return the default status of active
return {"active": True}


class WizParser(
WizParserByTitle,
Expand Down
20 changes: 20 additions & 0 deletions dojo/tools/wizcli_common_parsers/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,23 @@ def parse_os_packages(osPackages, test):
)
findings.append(finding)
return findings

@staticmethod
def convert_status(wiz_status) -> dict:
"""
Convert the Wiz Status to a dict of Finding status flags.
- Open-> Active = True
- Other statuses that may exist...
"""
if (status := wiz_status) is not None:
if status.upper() == "OPEN":
return {"active": True}
if status.upper() == "RESOLVED":
return {"active": False, "is_mitigated": True}
if status.upper() == "IGNORED":
return {"active": False, "out_of_scope": True}
if status.upper() == "IN_PROGRESS":
return {"active": True}
# Return the default status of active
return {"active": True}
8 changes: 4 additions & 4 deletions unittests/scans/wiz/multiple_findings.csv
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ An attacker that manages to execute code on the resource can use the publicly kn
* For private images, check the Finding for detailed information regarding the vulnerability.
* Build a new image with the fixed vulnerability and replace it in the resource.
* If you cannot use the latest version, prioritize patching resources in your environment according to the attack surface they are exposed to and the potential impact of this resource’s compromise (based on the Issue severity).",Wiz - Demo-Scenarios,https://demo.wiz.io/issues#~(issue~'027155e3-56a2-4916-9697-0c2202b9f5d1),https://portal.azure.com/#@wizsectest.onmicrosoft.com/resource//subscriptions/fee3535b-9616-486f-a476-6a500a08a02b/resourcegroups/us2eastrg/providers/microsoft.compute/virtualmachines/ms2012datacenterv001,{},,,
2023-01-25T00:19:57Z,AKS user/service accounts with the privileges to create pods,INFORMATIONAL,OPEN,"#### Description
2023-01-25T00:19:57Z,AKS user/service accounts with the privileges to create pods,INFORMATIONAL,IN_PROGRESS,"#### Description
This account is assigned the permission to create new pods.

#### Potential impact
Expand All @@ -73,7 +73,7 @@ Publicly exposed resources are more easily accessible for an attacker than inter
* Sensitive information should not be directly accessible from the internet, or accessible by easily-compromised principals.
* Limit the data access to only those who need it. Minimize the attack surface of users with access to sensitive data to protect from breaches.
* Make sure that the data is encrypted at rest.",Wiz - Demo-Scenarios,https://demo.wiz.io/issues#~(issue~'02ab10b7-e431-4349-b1ea-96db0aece24d),,{},,,
2024-01-24T11:02:11Z,AKS cluster contains a pod running containers with added capabilities,INFORMATIONAL,OPEN,"#### Description
2024-01-24T11:02:11Z,AKS cluster contains a pod running containers with added capabilities,INFORMATIONAL,RESOLVED,"#### Description
This cluster contains a pod running containers with added capabilities.

#### Potential impact
Expand All @@ -87,7 +87,7 @@ Containers run with a default set of capabilities as assigned by the Container R
* Avoid running privileged containers.
* Avoid sharing namespaces from the host to the container.
* Assign a network policy to namespaces so proper network segmentation is in place in case of a compromised container.",Wiz - Demo-Scenarios,https://demo.wiz.io/issues#~(issue~'02fd8a0d-16fa-4da0-aa49-a99694365d41),https://portal.azure.com/#@wizsectest.onmicrosoft.com/resource//subscriptions/fee3535b-9616-486f-a476-6a500a08a02b/resourcegroups/laliv_rg/providers/microsoft.containerservice/managedclusters/lalivaks,{},,,
2023-08-30T18:52:52Z,Container using an image with high/critical severity network vulnerabilities with a known exploit,LOW,OPEN,"#### Description
2023-08-30T18:52:52Z,Container using an image with high/critical severity network vulnerabilities with a known exploit,LOW,IGNORED,"#### Description
This container has a critical/high severity network vulnerability [based on CVSS](https://docs.wiz.io/wiz-docs/docs/controls-issues#control-severity) with a known exploit in the wild.

#### Potential impact
Expand All @@ -97,7 +97,7 @@ An attacker that manages to execute code on the public container can exploit the
* For private images, check the Finding for detailed information regarding the vulnerability.
* Build a new image with the fixed vulnerability and replace it in the resource.
* If you cannot use the latest version, prioritize patching resources in your environment according to the attack surface they are exposed to and the potential impact of this resource’s compromise (based on the Issue severity).",Wiz - Demo-Scenarios,https://demo.wiz.io/issues#~(issue~'030c78d3-0509-4565-8083-d83cd8c0dc96),,"{""app.kubernetes.io/instance"": ""sb-nginx-aks""}",,,
2023-01-24T22:09:36Z,Container using an image with high/critical severity network vulnerabilities with a known exploit,LOW,OPEN,"#### Description
2023-01-24T22:09:36Z,Container using an image with high/critical severity network vulnerabilities with a known exploit,LOW,IGNORED,"#### Description
This container has a critical/high severity network vulnerability [based on CVSS](https://docs.wiz.io/wiz-docs/docs/controls-issues#control-severity) with a known exploit in the wild.

#### Potential impact
Expand Down
19 changes: 19 additions & 0 deletions unittests/tools/test_wiz_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,25 @@ def test_multiple_findings(self):
finding = findings[1]
self.assertEqual("Unusual activity by a principal from previously unseen country", finding.title)
self.assertEqual("High", finding.severity)

finding = findings[7]
self.assertEqual("AKS user/service accounts with the privileges to create pods", finding.title)
self.assertEqual(True, finding.active)
self.assertEqual(False, finding.is_mitigated)
self.assertEqual(False, finding.out_of_scope)

finding = findings[9]
self.assertEqual("AKS cluster contains a pod running containers with added capabilities", finding.title)
self.assertEqual(False, finding.active)
self.assertEqual(True, finding.is_mitigated)
self.assertEqual(False, finding.out_of_scope)

finding = findings[11]
self.assertEqual("Container using an image with high/critical severity network vulnerabilities with a known exploit", finding.title)
self.assertEqual(False, finding.active)
self.assertEqual(False, finding.is_mitigated)
self.assertEqual(True, finding.out_of_scope)

finding = findings[20]
self.assertEqual(
"User/service account with get/list/watch permissions on secrets in an AKS cluster", finding.title,
Expand Down

0 comments on commit ef49dac

Please sign in to comment.