def parse_findings()

in dusty/scanners/dast/zap/parser.py [0:0]


def parse_findings(data, scanner):
    """ Parse findings """
    log.debug("Parsing findings")
    zap_json = json.loads(data)
    for site in zap_json["site"]:
        for alert in site["alerts"]:
            description = list()
            if "desc" in alert:
                description.append(markdown.html_to_text(alert["desc"]))
            if "solution" in alert:
                description.append(
                    f'\n**Solution:**\n {markdown.html_to_text(alert["solution"])}')
            if "reference" in alert:
                description.append(
                    f'\n**Reference:**\n {markdown.html_to_text(alert["reference"])}')
            if "otherinfo" in alert:
                description.append(
                    f'\n**Other information:**\n {markdown.html_to_text(alert["otherinfo"])}')
            if alert["instances"]:
                description.append("\n**Instances:**\n")
                description.append("| URI | Method | Parameter | Attack | Evidence |")
                description.append("| --- | ------ | --------- | ------ | -------- |")
            # Prepare results
            finding_data = list()
            if scanner.config.get("split_by_endpoint", False):
                # Collect endpoints
                endpoints = list()
                for item in alert["instances"]:
                    if not item.get("uri", None):
                        continue
                    endpoint = url.parse_url(item.get("uri"))
                    if endpoint in endpoints:
                        continue
                    endpoints.append(endpoint)
                # Prepare data
                for endpoint in endpoints:
                    finding_data.append({
                        "title": f'{alert["name"]} on {endpoint.raw}',
                        "description": "\n".join(description + ["| {} |".format(" | ".join([
                            html.escape(markdown.markdown_table_escape(item.get("uri", "-"))),
                            html.escape(markdown.markdown_table_escape(item.get("method", "-"))),
                            html.escape(markdown.markdown_table_escape(item.get("param", "-"))),
                            html.escape(markdown.markdown_table_escape(item.get("attack", "-"))),
                            html.escape(markdown.markdown_table_escape(item.get("evidence", "-")))
                            ])) for item in alert["instances"] \
                                if item.get("uri", None) == endpoint.raw]),
                        "tool": scanner.get_name(),
                        "severity": constants.ZAP_SEVERITIES[alert["riskcode"]],
                        "confidence": constants.ZAP_CONFIDENCES[alert["confidence"]],
                        "endpoints": [endpoint]
                    })
            # Make one finding object if needed/requested
            if not finding_data:
                # Extend description
                for item in alert["instances"]:
                    description.append("| {} |".format(" | ".join([
                        html.escape(markdown.markdown_table_escape(item.get("uri", "-"))),
                        html.escape(markdown.markdown_table_escape(item.get("method", "-"))),
                        html.escape(markdown.markdown_table_escape(item.get("param", "-"))),
                        html.escape(markdown.markdown_table_escape(item.get("attack", "-"))),
                        html.escape(markdown.markdown_table_escape(item.get("evidence", "-")))
                    ])))
                # Endpoints (for backwards compatibility)
                endpoints = list()
                for item in alert["instances"]:
                    if not item.get("uri", None):
                        continue
                    endpoint = url.parse_url(item.get("uri"))
                    if endpoint in endpoints:
                        continue
                    endpoints.append(endpoint)
                # Data
                finding_data.append({
                    "title": alert["name"],
                    "description": "\n".join(description),
                    "tool": scanner.get_name(),
                    "severity": constants.ZAP_SEVERITIES[alert["riskcode"]],
                    "confidence": constants.ZAP_CONFIDENCES[alert["confidence"]],
                    "endpoints": endpoints
                })
            # Make finding objects
            for object_data in finding_data:
                finding = DastFinding(
                    title=object_data["title"],
                    description=object_data["description"]
                )
                finding.set_meta("tool", object_data["tool"])
                finding.set_meta("severity", object_data["severity"])
                finding.set_meta("confidence", object_data["confidence"])
                finding.set_meta("endpoints", object_data["endpoints"])
                log.debug(f"Endpoints: {finding.get_meta('endpoints')}")
                scanner.findings.append(finding)