From bfe55c0cf729466f7150a3f466791f43a10a35ef Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:52:40 -0700 Subject: [PATCH 1/8] add impact add impact since it is unused --- dojo/tools/asff/parser.py | 1 + unittests/tools/test_asff_parser.py | 1 + 2 files changed, 2 insertions(+) diff --git a/dojo/tools/asff/parser.py b/dojo/tools/asff/parser.py index ccd5eb3110..48c10e8775 100644 --- a/dojo/tools/asff/parser.py +++ b/dojo/tools/asff/parser.py @@ -81,6 +81,7 @@ def get_findings(self, file, test): severity=self.get_severity(item.get("Severity")), active=active, unique_id_from_tool=item.get("Id"), + impact=resource_arn_strings, ) if "Resources" in item: diff --git a/unittests/tools/test_asff_parser.py b/unittests/tools/test_asff_parser.py index fe01bb06cf..8a9c47a503 100644 --- a/unittests/tools/test_asff_parser.py +++ b/unittests/tools/test_asff_parser.py @@ -22,6 +22,7 @@ def common_check_finding(self, finding, data, index, guarddutydate=False): resource_arn_strings = ", ".join(resource_arns) control_description = data[index].get("Description", "") full_description = f"**AWS resource ARN:** {resource_arn_strings}\n\n{control_description}" + impact = resource_arn_strings self.assertEqual(finding.title, data[index]["Title"]) self.assertEqual(finding.description, full_description) if guarddutydate: From 241700d7039906a31f7ba4920c5862314fb1a6c6 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 1 Oct 2024 13:00:37 -0700 Subject: [PATCH 2/8] Update test_asff_parser.py --- unittests/tools/test_asff_parser.py | 1 - 1 file changed, 1 deletion(-) diff --git a/unittests/tools/test_asff_parser.py b/unittests/tools/test_asff_parser.py index 8a9c47a503..fe01bb06cf 100644 --- a/unittests/tools/test_asff_parser.py +++ b/unittests/tools/test_asff_parser.py @@ -22,7 +22,6 @@ def common_check_finding(self, finding, data, index, guarddutydate=False): resource_arn_strings = ", ".join(resource_arns) control_description = data[index].get("Description", "") full_description = f"**AWS resource ARN:** {resource_arn_strings}\n\n{control_description}" - impact = resource_arn_strings self.assertEqual(finding.title, data[index]["Title"]) self.assertEqual(finding.description, full_description) if guarddutydate: From a26eba4fc7497645db9f15a185b37ced0adc0ecc Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:22:49 -0700 Subject: [PATCH 3/8] Update parser.py --- dojo/tools/asff/parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dojo/tools/asff/parser.py b/dojo/tools/asff/parser.py index 48c10e8775..ce7131e111 100644 --- a/dojo/tools/asff/parser.py +++ b/dojo/tools/asff/parser.py @@ -71,6 +71,7 @@ def get_findings(self, file, test): full_description = f"**AWS resource ARN:** {resource_arn_strings}\n\n{control_description}" else: full_description = control_description + impact = None finding = Finding( title=item.get("Title"), From a525e87ed4380e9601a301e1b50bd4ef6386a904 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:07:58 -0700 Subject: [PATCH 4/8] Update parser.py --- dojo/tools/asff/parser.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dojo/tools/asff/parser.py b/dojo/tools/asff/parser.py index ce7131e111..dda61e9fa7 100644 --- a/dojo/tools/asff/parser.py +++ b/dojo/tools/asff/parser.py @@ -69,6 +69,7 @@ def get_findings(self, file, test): if resource_arns: resource_arn_strings = ", ".join(resource_arns) full_description = f"**AWS resource ARN:** {resource_arn_strings}\n\n{control_description}" + impact = resource_arn_strings else: full_description = control_description impact = None @@ -82,7 +83,7 @@ def get_findings(self, file, test): severity=self.get_severity(item.get("Severity")), active=active, unique_id_from_tool=item.get("Id"), - impact=resource_arn_strings, + impact=impact, ) if "Resources" in item: From 89ab77b035a5c82ccc6b0ccc72e4aa8119bd1bbf Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:19:32 -0700 Subject: [PATCH 5/8] Mend SCA imports contain locations which are similar to filePaths for the SAST scans This code will use the 'locations' for SCA scan outputs to do the same thing that's done for SAST 'filePaths'. Since a Finding report will either be from SAST or SCA, it is unlikely that a collision will happen, since those findings are inherently different from Mend. Since the filepaths is already being joined for the SAST implementation, if it is indeed SCA results instead, the same thing will happen except now with the appropriate locations of the library and vulnerability. Note: this is not from Mend Platform or the CLI Agent output, but rather the Mend SCA portal. There is a new Platform API that combines both SAST and SCA vulnerabilities, so a new parser at some point for that would be good, and then it's possible to rename this to 'Legacy' for the Mend parser, since the 'Platform' should be the new. --- dojo/tools/mend/parser.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 75ed871a6a..d2fd687fa2 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -92,6 +92,7 @@ def _build_common_output(node, lib_name=None): logger.exception("Error handling topFix node.") filepaths = [] + locations = [] if "sourceFiles" in node: try: sourceFiles_node = node.get("sourceFiles") @@ -102,6 +103,21 @@ def _build_common_output(node, lib_name=None): "Error handling local paths for vulnerability.", ) + if "locations" in node: + try: + locations_node = node.get("locations", []) + for location in locations_node: + path = location.get("path") + if path is not None: + locations.append(path) + except Exception: + logger.exception( + "Error handling local paths for vulnerability.", + ) + + if locations: + filepaths = locations + new_finding = Finding( title=title, test=test, From 62ea5ab7a3b765421eebe834d3eaccde9102a213 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:12:08 -0700 Subject: [PATCH 6/8] Update parser.py --- dojo/tools/mend/parser.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index d2fd687fa2..6bcc96f750 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -92,7 +92,6 @@ def _build_common_output(node, lib_name=None): logger.exception("Error handling topFix node.") filepaths = [] - locations = [] if "sourceFiles" in node: try: sourceFiles_node = node.get("sourceFiles") @@ -103,6 +102,7 @@ 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", []) @@ -117,6 +117,8 @@ def _build_common_output(node, lib_name=None): if locations: filepaths = locations + else: + filepaths = filepaths new_finding = Finding( title=title, From 8b26b286a59ed22030c09de33066ecd82e1d0bfd Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:39:59 -0700 Subject: [PATCH 7/8] adding unit test for mend_sca_vulns from Mend SCA portal Mend has gone through some updates. Historically they've been SAST and then SCA, with their own separate portals. They are joining to a Mend Platform that contains both SAST+SCA+other vulnerabilities. This parser originally looks like it was based on Mend SAST, but I have been using it for SCA also since the vulnerabilities.json output files were similarly structured. This parser change hopes to update this to extract the location and path from an SCA.json and provide that as the file path. SAST calls this in a different way than SCA, which is why I think file path can be reused for both - depending on the file context found. I hope this code reflects that goal. To note: this was not a CLI or Unified Agent generated output file, but rather from downloading the Mend SCA portal API vulnerability data and uploading the returned vuln.json files using this parser. There may be a need in the future to add a parser that can correctly accept the updated format from the Mend Portal which contains combined vulnerability data sets, and the API response .json is different, so the parser does not work for the new Mend Platform returned .json, as experienced. --- unittests/scans/mend/mend_sca_vuln.json | 56 +++++++++++++++++++++++++ unittests/tools/test_mend_parser.py | 8 ++++ 2 files changed, 64 insertions(+) create mode 100644 unittests/scans/mend/mend_sca_vuln.json diff --git a/unittests/scans/mend/mend_sca_vuln.json b/unittests/scans/mend/mend_sca_vuln.json new file mode 100644 index 0000000000..6af95cb315 --- /dev/null +++ b/unittests/scans/mend/mend_sca_vuln.json @@ -0,0 +1,56 @@ +{ + "vulnerabilities": [ + { + "name": "WS-2019-0379", + "type": "WS", + "severity": "medium", + "score": "6.5", + "cvss3_severity": "MEDIUM", + "cvss3_score": "6.5", + "publishDate": "2019-05-20", + "lastUpdatedDate": "2020-03-05", + "scoreMetadataVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N", + "description": "Apache commons-codec before version \\u201ccommons-codec-1.13-RC1\\u201d is vulnerable to information disclosure due to Improper Input validation.", + "project": "mend-test-sca-project", + "product": "mend-test-sca-product", + "cvss3Attributes": { + "attackVector": "NETWORK", + "attackComplexity": "LOW", + "userInteraction": "NONE", + "privilegesRequired": "NONE", + "scope": "UNCHANGED", + "confidentialityImpact": "LOW", + "integrityImpact": "LOW", + "availabilityImpact": "NONE" + }, + "library": { + "keyUuid": "e4ad5291-19e0-4907-9cf1-5ce5a1746e89", + "filename": "commons-codec-1.6.jar", + "type": "JAVA_ARCHIVE", + "description": "", + "sha1": "b7f0fc8f61ecadeb3695f0b9464755eee44374d4", + "name": "commons-codec-1.6", + "artifactId": "commons-codec-1.6.jar", + "version": "1.6", + "groupId": "commons-codec-1.6", + "architecture": "", + "languageVersion": "" + }, + "topFix": { + "vulnerability": "WS-2019-0379", + "type": "UPGRADE_VERSION", + "origin": "WHITESOURCE_EXPERT", + "url": "https://github.com/apache/commons-codec/commit/48b615756d1d770091ea3322eefc08011ee8b113", + "fixResolution": "Upgrade to version commons-codec:commons-codec:1.13", + "date": "2019-05-20 15:39:18", + "message": "Upgrade to version" + }, + "locations": [ + { + "matchType": "Exact Match", + "path": "D:\\MendRepo\\test-product\\test-project\\test-project-subcomponent\\path\\to\\the\\Java\\commons-codec-1.6_donotuse.jar" + } + ] + } + ] +} \ No newline at end of file diff --git a/unittests/tools/test_mend_parser.py b/unittests/tools/test_mend_parser.py index 393dd4097c..d5914a30bf 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -35,3 +35,11 @@ def test_parse_file_with_multiple_vuln_cli_output(self): parser = MendParser() findings = parser.get_findings(testfile, Test()) self.assertEqual(20, len(findings)) + + def test_parse_file_with_one_sca_vuln_finding(self): + with open("unittests/scans/mend/mend_sca_vuln.json", encoding="utf-8") as testfile: + parser = MendParser() + 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) \ No newline at end of file From 72c6a878cb0c0eee5ba0ac23cb3eb54976174dab Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:41:57 -0700 Subject: [PATCH 8/8] Update test_mend_parser.py --- unittests/tools/test_mend_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/tools/test_mend_parser.py b/unittests/tools/test_mend_parser.py index d5914a30bf..1cd8cc11dd 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -42,4 +42,4 @@ 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) \ No newline at end of file + self.assertEqual("D:\\MendRepo\\test-product\\test-project\\test-project-subcomponent\\path\\to\\the\\Java\\commons-codec-1.6_donotuse.jar", finding.file_path)