diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index d397f3490e9..cc18bf3175e 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -39,6 +39,7 @@ def _build_common_output(node, lib_name=None): description = "No Description Available" cvss3_score = None mitigation = "N/A" + locations = [] if "component" in node: description = ( "**Vulnerability Description**: " @@ -56,18 +57,19 @@ def _build_common_output(node, lib_name=None): + "**Library Type**: " + node["component"].get("libraryType", "") + "\n" - + "**Location Found**: " - + node["component"].get("path", "") - + "\n" - + "**Direct or Transitive Dependency**: " - + node["component"].get("dependencyType", "") - + "\n" ) lib_name = node["component"].get("name") component_name = node["component"].get("artifactId") component_version = node["component"].get("version") - impact = node["component"].get("dependencyType") + impact = ( + "**Direct or Transitive Vulnerability**: " + + node["component"].get("dependencyType", "") + + "\n" + ) cvss3_score = node["vulnerability"].get("score", None) + component_path = node["component"].get("path", None) + if component_path: + locations.append(component_path) if "topFix" in node: try: topfix_node = node.get("topFix") @@ -82,7 +84,6 @@ def _build_common_output(node, lib_name=None): ) except Exception: logger.exception("Error handling topFix node.") - elif "library" in node: node.get("project") description = ( @@ -136,18 +137,6 @@ def _build_common_output(node, lib_name=None): ) cwe = 1035 # default OWASP a9 until the report actually has them - # comment out the below for now - working on adding this into the above conditional statements since format can be slightly different - # mitigation = "N/A" - # if "topFix" in node: - # try: - # topfix_node = node.get("topFix") - # mitigation = "**Resolution** ({}): {}\n".format( - # topfix_node.get("date"), - # topfix_node.get("fixResolution"), - # ) - # except Exception: - # logger.exception("Error handling topFix node.") - filepaths = [] if "sourceFiles" in node: try: @@ -159,7 +148,6 @@ def _build_common_output(node, lib_name=None): "Error handling local paths for vulnerability.", ) - locations = [] if "locations" in node: try: locations_node = node.get("locations", []) @@ -171,8 +159,31 @@ def _build_common_output(node, lib_name=None): logger.exception( "Error handling local paths for vulnerability.", ) + if locations: + # Join the locations into a single string + joined_locations = ", ".join(locations) + + # If the length exceeds 3999 characters, trim it + if len(joined_locations) > 3999: + # Iterate over the locations and trim until the total length is <= 3999 + total_length = 0 + truncated_locations = [] + + for loc in locations: + loc_length = len(loc) + # Check if adding this location will exceed the limit + if total_length + loc_length + len(truncated_locations) <= 3996: # 3999 - len("...") = 3996 + truncated_locations.append(loc) + total_length += loc_length + else: + # Stop if adding the next location will exceed the limit + break + + # Add ellipsis at the end to indicate truncation + locations = truncated_locations + locations.append("...") # Add the ellipsis to the end of the locations list - filepaths = locations or filepaths + filepaths = filepaths new_finding = Finding( title=title, @@ -188,7 +199,8 @@ def _build_common_output(node, lib_name=None): dynamic_finding=True, cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, - impact=impact, + impact=impact if impact is not None else None, + steps_to_reproduce="**Locations Found**: " + ", ".join(locations) if locations is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] @@ -238,7 +250,8 @@ def _build_common_output(node, lib_name=None): tree_node = content["response"] if tree_node: for node in tree_node: - findings.append(_build_common_output(node)) + if node.get("findingInfo", {}).get("status") == "ACTIVE": + findings.append(_build_common_output(node)) def create_finding_key(f: Finding) -> str: # """Hashes the finding's description and title to retrieve a key for deduplication.""" diff --git a/unittests/scans/mend/mend-sca-platform-api3-eleven-findings.json b/unittests/scans/mend/mend-sca-platform-api3-multiple-findings.json similarity index 100% rename from unittests/scans/mend/mend-sca-platform-api3-eleven-findings.json rename to unittests/scans/mend/mend-sca-platform-api3-multiple-findings.json diff --git a/unittests/tools/test_mend_parser.py b/unittests/tools/test_mend_parser.py index cd544d503c1..75bbd54bcbb 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -42,7 +42,8 @@ def test_parse_file_with_one_sca_vuln_finding(self): findings = parser.get_findings(testfile, Test()) self.assertEqual(1, len(findings)) finding = list(findings)[0] - self.assertEqual("D:\\MendRepo\\test-product\\test-project\\test-project-subcomponent\\path\\to\\the\\Java\\commons-codec-1.6_donotuse.jar", finding.file_path) + self.assertEqual("**Locations Found**: D:\\MendRepo\\test-product\\test-project\\test-project-subcomponent\\path\\to\\the\\Java\\commons-codec-1.6_donotuse.jar", finding.steps_to_reproduce) + self.assertEqual("WS-2019-0379 | commons-codec-1.6.jar", finding.title) def test_parse_file_with_no_vuln_has_no_findings_platform(self): with open("unittests/scans/mend/mend-sca-platform-api3-no-findings.json", encoding="utf-8") as testfile: @@ -60,9 +61,10 @@ def test_parse_file_with_one_vuln_has_one_findings_platform(self): self.assertEqual("CVE-2024-51744", finding.unsaved_vulnerability_ids[0]) self.assertEqual("CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N", finding.cvssv3) self.assertEqual(3.1, finding.cvssv3_score) + self.assertEqual("CVE-2024-51744 | github.com/golang-JWT/jwt-v3.2.2+incompatible", finding.title) def test_parse_file_with_multiple_vuln_has_multiple_finding_platform(self): - with open("unittests/scans/mend/mend-sca-platform-api3-eleven-findings.json", encoding="utf-8") as testfile: + with open("unittests/scans/mend/mend-sca-platform-api3-multiple-findings.json", encoding="utf-8") as testfile: parser = MendParser() findings = parser.get_findings(testfile, Test()) - self.assertEqual(11, len(findings)) + self.assertEqual(5, len(findings))