From f192eb6e8825b5570c7af076b3aaeeed2ac984da Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:35:14 -0800 Subject: [PATCH 01/50] Add unit test json files for Mend Platform - SAST Findings Code findings in API 3.0 / Platform for Mend, SAST respectively. --- .../mend-platform-sast-many-findings.json | 831 ++++++++++++++++++ .../mend/mend-platform-sast-no-findings.json | 1 + .../mend/mend-platform-sast-one-finding.json | 167 ++++ 3 files changed, 999 insertions(+) create mode 100644 unittests/scans/mend/mend-platform-sast-many-findings.json create mode 100644 unittests/scans/mend/mend-platform-sast-no-findings.json create mode 100644 unittests/scans/mend/mend-platform-sast-one-finding.json diff --git a/unittests/scans/mend/mend-platform-sast-many-findings.json b/unittests/scans/mend/mend-platform-sast-many-findings.json new file mode 100644 index 00000000000..3550e632cc3 --- /dev/null +++ b/unittests/scans/mend/mend-platform-sast-many-findings.json @@ -0,0 +1,831 @@ +{ + 'response': [ + { + 'id': '4b132785-06ea-485e-b813-10911afc3130', + 'scanId': '4c5e09b2-756e-47b2-ab7c-c2de08de5580', + 'snapshotId': '4c1ddc4f-d08e-4fb6-a358-58d494a4d58e', + 'projectId': 'bc929188-8fe0-4a30-975e-86fcfcf6328f', + 'appId': '3a48010d-ae5a-42df-81c5-836271f64f9d', + 'type': { + 'id': 1, + 'commonId': 'path-traversal-22', + 'name': 'Path/Directory Traversal', + 'engineId': 5, + 'language': 'Ruby', + 'sarif': 'ruby-path-traversal', + 'sarifLevel': '', + 'order': 4, + 'severity': 'High', + 'severityRating': 7.913, + 'description': 'Path/Directory Traversal or file disclosure vulnerability occurs when an external input is used to construct a pathname that is intended to identify a file or a directory located underneath a restricted parent directory. The application does not properly neutralize (sanitize) special elements within the pathname, which can cause the pathname to resolve to a location that is outside of the restricted directory. Successful file disclosure attack can result in sensitive files disclosure, and can often lead to full system compromise', + 'recommendations': [ + 'Using a whitelist of directories from which files are allowed for download and validating requests based on that list', + 'Indexing files which are allowed for download and passing only their index numbers as the URL parameter values', + 'Validating requested file types' + ], + 'references': [ + 'https://owasp.org/www-community/attacks/Path_Traversal' + ], + 'cwe': { + 'id': 'CWE-22', + 'title': "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')", + 'url': 'https://cwe.mitre.org/data/definitions/22.html' + }, + 'pcidss': { + 'section': '6.5.8', + 'title': 'PCI DSS 6.5.8: Improper Access Control' + }, + 'nist': { + 'control': 'SI-10', + 'priority': 'P1', + 'title': 'SI-10: Information Input Validation', + 'url': 'https://nvd.nist.gov/800-53/Rev5/control/SI-10' + }, + 'hipaa': { + 'control': '164.312 (a)(1)', + 'title': '164.312 (a)(1): Standard: Access control' + }, + 'hitrust': { + 'control': '10.b', + 'title': '10.b: Input Data Validation (Level 1 Implementation)' + }, + 'owasp': { + 'index': 'A5', + 'title': 'A5: Broken Access Control', + 'url': 'https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A5-Broken_Access_Control' + }, + 'owasp2021': { + 'index': 'A1', + 'title': 'A1: Broken Access Control', + 'url': 'https://owasp.org/Top10/A01_2021-Broken_Access_Control/' + }, + 'capec': { + 'id': '126', + 'title': 'CAPEC-126: Path Traversal', + 'url': 'https://capec.mitre.org/data/definitions/126.html' + }, + 'sansTop25': { + 'rank': 8, + 'title': "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + } + }, + 'description': 'open() method could be abused to reveal sensitive file content and/or write to arbitrary files.', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'severity': 'High', + 'baseline': True, + 'hasRemediation': False, + 'suppressed': False, + 'suppressedBy': '', + 'suppressionTime': '0001-01-01T00:00:00Z', + 'suppressionMessage': '', + 'reviewed': False, + 'IssueStatus': 0, + 'sharedStep': { + 'name': 'File.open ', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'File.open(name, "w")', + 'line': 379, + 'startLine': 375, + 'endLine': 384, + 'lineBlame': { + 'commitId': '', + 'file': '', + 'line': 0 + } + }, + 'dataFlows': [ + { + 'id': 'dba3a480-5408-47cc-be6a-fab8dda52917', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'sink': 'File.open ', + 'sinkKind': '', + 'sinkFile': 'src/codegen/generate.rb', + 'sinkSnippet': 'File.open(name, "w")', + 'sinkLine': 379, + 'inputSource': 'ARGV', + 'inputKind': '', + 'inputFlow': [ + { + 'name': 'ARGV', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 394, + 'endLine': 403 + }, + { + 'name': 'destdir', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', + 'line': 317, + 'startLine': 313, + 'endLine': 322 + }, + { + 'name': 'name', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def create_folder_and_open(name)', + 'line': 377, + 'startLine': 373, + 'endLine': 382 + } + ], + 'functionCalls': [ + { + 'name': 'File.open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'File.open(name, "w")', + 'line': 379, + 'startLine': 375, + 'endLine': 384 + }, + { + 'name': 'create_folder_and_open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'f = create_folder_and_open("#{destdir}#{accservice}/dto/testModify.java")', + 'line': 346, + 'startLine': 0, + 'endLine': 0 + }, + { + 'name': 'generate_acc', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 0, + 'endLine': 0 + } + ], + 'filter': { + 'isFiltered': False, + 'filterTypes': [] + }, + 'rating': 6.307692307692308, + 'confidenceRating': 6, + 'ageRating': 8 + }, + { + 'id': '96c3eab0-d5ac-486b-9bbf-2ab5bb36ee10', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'sink': 'File.open ', + 'sinkKind': '', + 'sinkFile': 'src/codegen/generate.rb', + 'sinkSnippet': 'File.open(name, "w")', + 'sinkLine': 379, + 'inputSource': 'ARGV', + 'inputKind': '', + 'inputFlow': [ + { + 'name': 'ARGV', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 394, + 'endLine': 403 + }, + { + 'name': 'destdir', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', + 'line': 317, + 'startLine': 313, + 'endLine': 322 + }, + { + 'name': 'name', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def create_folder_and_open(name)', + 'line': 377, + 'startLine': 373, + 'endLine': 382 + } + ], + 'functionCalls': [ + { + 'name': 'File.open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'File.open(name, "w")', + 'line': 379, + 'startLine': 375, + 'endLine': 384 + }, + { + 'name': 'create_folder_and_open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'f = create_folder_and_open(destdir + testservice + "/dto/responses/" + filename)', + 'line': 341, + 'startLine': 0, + 'endLine': 0 + }, + { + 'name': 'generate_acc', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 0, + 'endLine': 0 + } + ], + 'filter': { + 'isFiltered': False, + 'filterTypes': [] + }, + 'rating': 6.307692307692308, + 'confidenceRating': 6, + 'ageRating': 8 + }, + { + 'id': '408f3055-c076-4330-8ecb-c9e4f657472a', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'sink': 'File.open ', + 'sinkKind': '', + 'sinkFile': 'src/codegen/generate.rb', + 'sinkSnippet': 'File.open(name, "w")', + 'sinkLine': 379, + 'inputSource': 'ARGV', + 'inputKind': '', + 'inputFlow': [ + { + 'name': 'ARGV', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 394, + 'endLine': 403 + }, + { + 'name': 'destdir', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', + 'line': 317, + 'startLine': 313, + 'endLine': 322 + }, + { + 'name': 'name', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def create_folder_and_open(name)', + 'line': 377, + 'startLine': 373, + 'endLine': 382 + } + ], + 'functionCalls': [ + { + 'name': 'File.open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'File.open(name, "w")', + 'line': 379, + 'startLine': 375, + 'endLine': 384 + }, + { + 'name': 'create_folder_and_open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'f = create_folder_and_open(destdir + testservice + "/dto/requests/" + filename)', + 'line': 334, + 'startLine': 0, + 'endLine': 0 + }, + { + 'name': 'generate_acc', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 0, + 'endLine': 0 + } + ], + 'filter': { + 'isFiltered': False, + 'filterTypes': [] + }, + 'rating': 6.307692307692308, + 'confidenceRating': 6, + 'ageRating': 8 + }, + { + 'id': 'f319f409-6021-40fd-8f0a-de36e52a93d9', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'sink': 'File.open ', + 'sinkKind': '', + 'sinkFile': 'src/codegen/generate.rb', + 'sinkSnippet': 'File.open(name, "w")', + 'sinkLine': 379, + 'inputSource': 'ARGV', + 'inputKind': '', + 'inputFlow': [ + { + 'name': 'ARGV', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 394, + 'endLine': 403 + }, + { + 'name': 'destdir', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', + 'line': 317, + 'startLine': 313, + 'endLine': 322 + }, + { + 'name': 'name', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def create_folder_and_open(name)', + 'line': 377, + 'startLine': 373, + 'endLine': 382 + } + ], + 'functionCalls': [ + { + 'name': 'File.open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'File.open(name, "w")', + 'line': 379, + 'startLine': 375, + 'endLine': 384 + }, + { + 'name': 'create_folder_and_open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'f = create_folder_and_open(destdir + testservice + "/impl/" + filename)', + 'line': 328, + 'startLine': 0, + 'endLine': 0 + }, + { + 'name': 'generate_acc', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 0, + 'endLine': 0 + } + ], + 'filter': { + 'isFiltered': False, + 'filterTypes': [] + }, + 'rating': 6.307692307692308, + 'confidenceRating': 6, + 'ageRating': 8 + }, + { + 'id': '4c376010-9ea8-4c99-84dc-994dab9baeac', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'sink': 'File.open ', + 'sinkKind': '', + 'sinkFile': 'src/codegen/generate.rb', + 'sinkSnippet': 'File.open(name, "w")', + 'sinkLine': 379, + 'inputSource': 'ARGV', + 'inputKind': '', + 'inputFlow': [ + { + 'name': 'ARGV', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 394, + 'endLine': 403 + }, + { + 'name': 'destdir', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', + 'line': 317, + 'startLine': 313, + 'endLine': 322 + }, + { + 'name': 'name', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'def create_folder_and_open(name)', + 'line': 377, + 'startLine': 373, + 'endLine': 382 + } + ], + 'functionCalls': [ + { + 'name': 'File.open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'File.open(name, "w")', + 'line': 379, + 'startLine': 375, + 'endLine': 384 + }, + { + 'name': 'create_folder_and_open', + 'kind': '', + 'file': 'src/codegen/generate.rb', + 'snippet': 'f = create_folder_and_open(destdir + testservice + "/" + filename)', + 'line': 323, + 'startLine': 0, + 'endLine': 0 + }, + { + 'name': 'generate_acc', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': 'import com.foxt.acc.exception.LevelType;', + 'line': 398, + 'startLine': 0, + 'endLine': 0 + } + ], + 'filter': { + 'isFiltered': False, + 'filterTypes': [] + }, + 'rating': 6.307692307692308, + 'confidenceRating': 6, + 'ageRating': 8 + } + ], + 'severityRating': 7.913, + 'confidenceRating': 6, + 'ageRating': 0, + 'rating': 3.7982400000000003, + 'almIssues': { + 'jira': { + 'issueId': '', + 'project': '' + }, + 'azure': { + 'workItemId': 0, + 'project': '' + }, + 'jiraPlatform': { + 'internalStatus': '', + 'issueStatus': '', + 'issueKey': '', + 'publicLink': '', + 'createdTime': '0001-01-01T00:00:00Z', + 'createdBy': '', + 'createdByName': '' + } + }, + 'comments': [], + 'workflowViolationsCount': 0, + 'workflowViolations': [] + }, + { + 'id': '240f8300-fe4c-4602-83f7-656deec30222', + 'scanId': '4c5e09b2-756e-47b2-ab7c-c2de08de5580', + 'snapshotId': 'aed0bec0-2067-472f-aa84-66d2e7ef9b16', + 'projectId': 'bc929188-8fe0-4a30-975e-86fcfcf6328f', + 'appId': '3a48010d-ae5a-42df-81c5-836271f64f9d', + 'type': { + 'id': 10, + 'commonId': 'weak-hash-916', + 'name': 'Weak Hash Strength', + 'engineId': 5, + 'language': 'Ruby', + 'sarif': 'ruby-weak-hash', + 'sarifLevel': '', + 'order': 16, + 'severity': 'Low', + 'severityRating': 2.987, + 'description': 'The application generates a hash but it uses a scheme that does not provide a sufficient level of computational effort that would make cracking attacks infeasible or expensive', + 'recommendations': [ + 'Use an adaptive hash function that can be configured to change the amount of computational effort needed to compute the hash, such as the number of iterations ("stretching") or the amount of memory required. Some hash functions perform salting automatically. These functions can significantly increase the overhead for a brute force attack compared to intentionally-fast functions such as MD5' + ], + 'references': [ + 'https://www.owasp.org/index.php/Testing_for_Weak_Encryption_(OTG-CRYPST-004)' + ], + 'cwe': { + 'id': 'CWE-916', + 'title': 'CWE-916: Use of Password Hash With Insufficient Computational Effort', + 'url': 'https://cwe.mitre.org/data/definitions/916.html' + }, + 'pcidss': { + 'section': '6.5.3', + 'title': 'PCI DSS 6.5.3: Insecure Cryptographic Storage' + }, + 'nist': { + 'control': 'SC-13', + 'priority': 'P1', + 'title': 'SC-13: Cryptographic Protection', + 'url': 'https://nvd.nist.gov/800-53/Rev5/control/SC-13' + }, + 'hipaa': { + 'control': '164.312 (a)(2)(iv)', + 'title': '164.312 (a)(2)(iv): Access Control: Encryption and Decryption' + }, + 'hitrust': { + 'control': '', + 'title': '' + }, + 'owasp': { + 'index': 'A3', + 'title': 'A3: Sensitive Data Exposure', + 'url': 'https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A3-Sensitive_Data_Exposure' + }, + 'owasp2021': { + 'index': 'A2', + 'title': 'A2: Cryptographic Failures', + 'url': 'https://owasp.org/Top10/A02_2021-Cryptographic_Failures/' + }, + 'capec': { + 'id': '97', + 'title': 'CAPEC-97: Cryptanalysis', + 'url': 'https://capec.mitre.org/data/definitions/97.html' + }, + 'sansTop25': { + 'rank': 0, + 'title': '' + } + }, + 'description': 'It is not advised to use weak cryptographic function.', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'severity': 'Low', + 'baseline': True, + 'hasRemediation': False, + 'suppressed': False, + 'suppressedBy': '', + 'suppressionTime': '0001-01-01T00:00:00Z', + 'suppressionMessage': '', + 'reviewed': False, + 'IssueStatus': 0, + 'sharedStep': { + 'name': 'Weak cryptographic function ', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': "'sha512SaltLen'", + 'line': 141, + 'startLine': 137, + 'endLine': 146, + 'lineBlame': { + 'commitId': '', + 'file': '', + 'line': 0 + } + }, + 'dataFlows': [ + { + 'id': '2ec00687-01c6-48e0-8891-1f6f3b314438', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'sink': 'Weak cryptographic function ', + 'sinkKind': '', + 'sinkFile': 'src/codegen/acc_proto.rb', + 'sinkSnippet': "'sha512SaltLen'", + 'sinkLine': 141, + 'inputSource': 'Weak cryptographic function - sha', + 'inputKind': '', + 'inputFlow': [ + { + 'name': 'Weak cryptographic function', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': "'sha512SaltLen'", + 'line': 141, + 'startLine': 0, + 'endLine': 0 + } + ], + 'functionCalls': [ + { + 'name': 'Insecure cryptographic function', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': "'sha512SaltLen'", + 'line': 141, + 'startLine': 137, + 'endLine': 146 + } + ], + 'filter': { + 'isFiltered': False, + 'filterTypes': [] + }, + 'rating': 9.692307692307692, + 'confidenceRating': 10, + 'ageRating': 8 + } + ], + 'severityRating': 2.987, + 'confidenceRating': 10, + 'ageRating': 0, + 'rating': 2.3896, + 'almIssues': { + 'jira': { + 'issueId': '', + 'project': '' + }, + 'azure': { + 'workItemId': 0, + 'project': '' + }, + 'jiraPlatform': { + 'internalStatus': '', + 'issueStatus': '', + 'issueKey': '', + 'publicLink': '', + 'createdTime': '0001-01-01T00:00:00Z', + 'createdBy': '', + 'createdByName': '' + } + }, + 'comments': [], + 'workflowViolationsCount': 0, + 'workflowViolations': [] + }, + { + 'id': '2ca40933-ada9-436a-b021-8065f1352d45', + 'scanId': '4c5e09b2-756e-47b2-ab7c-c2de08de5580', + 'snapshotId': 'db2fd7d0-83c1-4c4d-8613-fa782328e78f', + 'projectId': 'bc929188-8fe0-4a30-975e-86fcfcf6328f', + 'appId': '3a48010d-ae5a-42df-81c5-836271f64f9d', + 'type': { + 'id': 10, + 'commonId': 'weak-hash-916', + 'name': 'Weak Hash Strength', + 'engineId': 5, + 'language': 'Ruby', + 'sarif': 'ruby-weak-hash', + 'sarifLevel': '', + 'order': 16, + 'severity': 'Low', + 'severityRating': 2.987, + 'description': 'The application generates a hash but it uses a scheme that does not provide a sufficient level of computational effort that would make cracking attacks infeasible or expensive', + 'recommendations': [ + 'Use an adaptive hash function that can be configured to change the amount of computational effort needed to compute the hash, such as the number of iterations ("stretching") or the amount of memory required. Some hash functions perform salting automatically. These functions can significantly increase the overhead for a brute force attack compared to intentionally-fast functions such as MD5' + ], + 'references': [ + 'https://www.owasp.org/index.php/Testing_for_Weak_Encryption_(OTG-CRYPST-004)' + ], + 'cwe': { + 'id': 'CWE-916', + 'title': 'CWE-916: Use of Password Hash With Insufficient Computational Effort', + 'url': 'https://cwe.mitre.org/data/definitions/916.html' + }, + 'pcidss': { + 'section': '6.5.3', + 'title': 'PCI DSS 6.5.3: Insecure Cryptographic Storage' + }, + 'nist': { + 'control': 'SC-13', + 'priority': 'P1', + 'title': 'SC-13: Cryptographic Protection', + 'url': 'https://nvd.nist.gov/800-53/Rev5/control/SC-13' + }, + 'hipaa': { + 'control': '164.312 (a)(2)(iv)', + 'title': '164.312 (a)(2)(iv): Access Control: Encryption and Decryption' + }, + 'hitrust': { + 'control': '', + 'title': '' + }, + 'owasp': { + 'index': 'A3', + 'title': 'A3: Sensitive Data Exposure', + 'url': 'https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A3-Sensitive_Data_Exposure' + }, + 'owasp2021': { + 'index': 'A2', + 'title': 'A2: Cryptographic Failures', + 'url': 'https://owasp.org/Top10/A02_2021-Cryptographic_Failures/' + }, + 'capec': { + 'id': '97', + 'title': 'CAPEC-97: Cryptanalysis', + 'url': 'https://capec.mitre.org/data/definitions/97.html' + }, + 'sansTop25': { + 'rank': 0, + 'title': '' + } + }, + 'description': 'It is not advised to use weak cryptographic function.', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'severity': 'Low', + 'baseline': True, + 'hasRemediation': False, + 'suppressed': False, + 'suppressedBy': '', + 'suppressionTime': '0001-01-01T00:00:00Z', + 'suppressionMessage': '', + 'reviewed': False, + 'IssueStatus': 0, + 'sharedStep': { + 'name': 'Weak cryptographic function ', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': "'sha512Rounds',", + 'line': 140, + 'startLine': 136, + 'endLine': 145, + 'lineBlame': { + 'commitId': '', + 'file': '', + 'line': 0 + } + }, + 'dataFlows': [ + { + 'id': '2a3cd60d-2579-4557-889e-f43855f44ba5', + 'createdTime': '2024-08-08T06:27:38.811Z', + 'sink': 'Weak cryptographic function ', + 'sinkKind': '', + 'sinkFile': 'src/codegen/acc_proto.rb', + 'sinkSnippet': "'sha512Rounds',", + 'sinkLine': 140, + 'inputSource': 'Weak cryptographic function - sha', + 'inputKind': '', + 'inputFlow': [ + { + 'name': 'Weak cryptographic function', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': "'sha512Rounds',", + 'line': 140, + 'startLine': 0, + 'endLine': 0 + } + ], + 'functionCalls': [ + { + 'name': 'Insecure cryptographic function', + 'kind': '', + 'file': 'src/codegen/acc_proto.rb', + 'snippet': "'sha512Rounds',", + 'line': 140, + 'startLine': 136, + 'endLine': 145 + } + ], + 'filter': { + 'isFiltered': False, + 'filterTypes': [] + }, + 'rating': 9.692307692307692, + 'confidenceRating': 10, + 'ageRating': 8 + } + ], + 'severityRating': 2.987, + 'confidenceRating': 10, + 'ageRating': 0, + 'rating': 2.3896, + 'almIssues': { + 'jira': { + 'issueId': '', + 'project': '' + }, + 'azure': { + 'workItemId': 0, + 'project': '' + }, + 'jiraPlatform': { + 'internalStatus': '', + 'issueStatus': '', + 'issueKey': '', + 'publicLink': '', + 'createdTime': '0001-01-01T00:00:00Z', + 'createdBy': '', + 'createdByName': '' + } + }, + 'comments': [], + 'workflowViolationsCount': 0, + 'workflowViolations': [] + } + ], + 'additionalData': None, + 'supportToken': 'b2f7a762258bbe6b842c1b6fccd75eb9756e84f0d3973058' +} \ No newline at end of file diff --git a/unittests/scans/mend/mend-platform-sast-no-findings.json b/unittests/scans/mend/mend-platform-sast-no-findings.json new file mode 100644 index 00000000000..cf31cbe997d --- /dev/null +++ b/unittests/scans/mend/mend-platform-sast-no-findings.json @@ -0,0 +1 @@ +{'response': [], 'additionalData': None, 'supportToken': '12345fca9ac7329360d302ce711c84eb3917a06c9747f7b7'} \ No newline at end of file diff --git a/unittests/scans/mend/mend-platform-sast-one-finding.json b/unittests/scans/mend/mend-platform-sast-one-finding.json new file mode 100644 index 00000000000..2e59a8f0e92 --- /dev/null +++ b/unittests/scans/mend/mend-platform-sast-one-finding.json @@ -0,0 +1,167 @@ +{ + 'response': [ + { + 'id': '42f09f21-7e77-45bb-9af0-1750b9664faf', + 'scanId': 'b5e748b4-a6ff-4303-89a6-b051062fa5e3', + 'snapshotId': 'e84dc715-b34e-43ba-8ad3-ff9303dcff54', + 'projectId': '4a84dc99-256b-460f-8af3-7e33ad9e8f00', + 'appId': 'd3faf1a5-65b5-4817-a6dc-c6862faebd63', + 'type': { + 'id': 55, + 'commonId': 'crypto-missing-step-325', + 'name': 'Missing Cryptographic Step', + 'engineId': 101, + 'language': 'Java*', + 'sarif': 'java-crypto-missing-step', + 'sarifLevel': '', + 'order': 35, + 'severity': 'Low', + 'severityRating': 2.143, + 'description': 'The application does not implement or incorrectly implements a necessary step in a cryptographic process. Such omission or error can lead to security vulnerabilities and weaken the overall effectiveness of the cryptographic process', + 'recommendations': [ + 'Check if all the necessary steps for a cryptographic process have been implemented' + ], + 'references': [ + 'https://cwe.mitre.org/data/definitions/325.html' + ], + 'cwe': { + 'id': 'CWE-325', + 'title': 'CWE-325: Missing Cryptographic Step', + 'url': 'https://cwe.mitre.org/data/definitions/325.html' + }, + 'pcidss': { + 'section': '6.5.3', + 'title': 'PCI DSS 6.5.3: Insecure Cryptographic Storage' + }, + 'nist': { + 'control': 'SC-13', + 'priority': 'P1', + 'title': 'SC-13: Cryptographic Protection', + 'url': 'https://nvd.nist.gov/800-53/Rev5/control/SC-13' + }, + 'hipaa': { + 'control': '164.312 (a)(2)(iv)', + 'title': '164.312 (a)(2)(iv): Access Control: Encryption and Decryption' + }, + 'hitrust': { + 'control': '', + 'title': '' + }, + 'owasp': { + 'index': 'A3', + 'title': 'A3: Sensitive Data Exposure', + 'url': 'https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure' + }, + 'owasp2021': { + 'index': 'A2', + 'title': 'A2: Cryptographic Failures', + 'url': 'https://owasp.org/Top10/A02_2021-Cryptographic_Failures/' + }, + 'capec': { + 'id': '97', + 'title': 'CAPEC-97: Cryptanalysis', + 'url': 'https://capec.mitre.org/data/definitions/97.html' + }, + 'sansTop25': { + 'rank': 0, + 'title': '' + } + }, + 'description': "'init' method of 'javax.crypto.KeyGenerator' uses a crypto algorithm in a wrong way. Key size is not valid", + 'createdTime': '2024-08-12T06:37:37.336Z', + 'severity': 'Low', + 'baseline': True, + 'hasRemediation': False, + 'suppressed': False, + 'suppressedBy': '', + 'suppressionTime': '0001-01-01T00:00:00Z', + 'suppressionMessage': '', + 'reviewed': False, + 'IssueStatus': 0, + 'sharedStep': { + 'name': 'javax.crypto.KeyGenerator.init', + 'kind': '', + 'file': 'src/com/foxt/password/PasswordCryptFile.java', + 'snippet': 'kg.init(klen);', + 'line': 145, + 'startLine': 141, + 'endLine': 150, + 'lineBlame': { + 'commitId': '', + 'file': '', + 'line': 0 + } + }, + 'dataFlows': [ + { + 'id': 'cfab7e98-23fb-4028-8f12-36c69355ec5c', + 'createdTime': '2024-08-12T06:37:37.336Z', + 'sink': 'javax.crypto.KeyGenerator.init', + 'sinkKind': '', + 'sinkFile': 'src/com/foxt/password/PasswordCryptFile.java', + 'sinkSnippet': 'kg.init(klen);', + 'sinkLine': 145, + 'inputSource': 'kg', + 'inputKind': 'variable', + 'inputFlow': [ + { + 'name': 'kg', + 'kind': 'variable', + 'file': 'src/com/foxt/password/PasswordCryptFile.java', + 'snippet': 'KeyGenerator kg = KeyGenerator.getInstance(s_algorithm);', + 'line': 139, + 'startLine': 135, + 'endLine': 144 + } + ], + 'functionCalls': [ + { + 'name': 'javax.crypto.KeyGenerator.init', + 'kind': '', + 'file': 'src/com/foxt/password/PasswordCryptFile.java', + 'snippet': 'kg.init(klen);', + 'line': 145, + 'startLine': 141, + 'endLine': 150 + } + ], + 'filter': { + 'isFiltered': False, + 'filterTypes': [] + }, + 'rating': 9.692307692307692, + 'confidenceRating': 10, + 'ageRating': 8 + } + ], + 'severityRating': 2.143, + 'confidenceRating': 10, + 'ageRating': 0, + 'rating': 1.7144, + 'almIssues': { + 'jira': { + 'issueId': '', + 'project': '' + }, + 'azure': { + 'workItemId': 0, + 'project': '' + }, + 'jiraPlatform': { + 'internalStatus': '', + 'issueStatus': '', + 'issueKey': '', + 'publicLink': '', + 'createdTime': '0001-01-01T00:00:00Z', + 'createdBy': '', + 'createdByName': '' + } + }, + 'comments': [], + 'workflowViolationsCount': 0, + 'workflowViolations': [] + } + ], + 'additionalData': None, + 'supportToken': '4ca13f5d1a546e16da5e518408ea99ac6dc3b2d245aceff6' +} \ No newline at end of file From 52e9388d809fc54df40d8b4128a589f895299efe Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:48:37 -0800 Subject: [PATCH 02/50] Update test_mend_parser.py --- unittests/tools/test_mend_parser.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/unittests/tools/test_mend_parser.py b/unittests/tools/test_mend_parser.py index cd544d503c1..18651a48ba4 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -66,3 +66,26 @@ def test_parse_file_with_multiple_vuln_has_multiple_finding_platform(self): parser = MendParser() findings = parser.get_findings(testfile, Test()) self.assertEqual(11, len(findings)) + + def test_parse_file_with_no_vuln_has_no_findings_platform_sast(self): + with open("unittests/scans/mend/mend-platform-sast-no-findings.json", encoding="utf-8") as testfile: + parser = MendParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) + + def test_parse_file_with_one_vuln_has_one_findings_platform_sast(self): + with open("unittests/scans/mend/mend-platform-sast-one-finding.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(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CWE-325", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("10", finding.cvssv3) + self.assertEqual(3.1, finding.cvssv3_score) + + def test_parse_file_with_multiple_vuln_has_multiple_finding_platform_sast(self): + with open("unittests/scans/mend/mend-platform-sast-many-findings.json", encoding="utf-8") as testfile: + parser = MendParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) \ No newline at end of file From 7d9b03786470daf94696c01a41fbcfa233548819 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:49:44 -0800 Subject: [PATCH 03/50] Fix newline eof --- 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 18651a48ba4..03be1856eb6 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -88,4 +88,4 @@ def test_parse_file_with_multiple_vuln_has_multiple_finding_platform_sast(self): with open("unittests/scans/mend/mend-platform-sast-many-findings.json", encoding="utf-8") as testfile: parser = MendParser() findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) \ No newline at end of file + self.assertEqual(3, len(findings)) From 69de822087492867797a612abb2b0f03390fb380 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:56:15 -0800 Subject: [PATCH 04/50] Update parser.py Remove locations / path from Description of SCA Platform output and instead implement locations in steps_to_reproduce. --- dojo/tools/mend/parser.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index d397f3490e9..fde27c187e0 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -56,9 +56,6 @@ 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" @@ -172,7 +169,8 @@ def _build_common_output(node, lib_name=None): "Error handling local paths for vulnerability.", ) - filepaths = locations or filepaths + filepaths = filepaths + steps_to_reproduce = locations new_finding = Finding( title=title, @@ -189,6 +187,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, + steps_to_reproduce=steps_to_reproduce if steps_to_reproduce is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From f014e94c43dbf9d4683e3d0037d0b21b19cfc959 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:59:54 -0800 Subject: [PATCH 05/50] Update test_mend_parser.py Updating value to a placeholder severityRating right now of 2.143. Still working on this and the cvssv3 assertion values. --- 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 03be1856eb6..1c7817a2330 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -82,7 +82,7 @@ def test_parse_file_with_one_vuln_has_one_findings_platform_sast(self): self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) self.assertEqual("CWE-325", finding.unsaved_vulnerability_ids[0]) self.assertEqual("10", finding.cvssv3) - self.assertEqual(3.1, finding.cvssv3_score) + self.assertEqual(2.143, finding.cvssv3_score) def test_parse_file_with_multiple_vuln_has_multiple_finding_platform_sast(self): with open("unittests/scans/mend/mend-platform-sast-many-findings.json", encoding="utf-8") as testfile: From 6aa852efc9bd34a545f594b2f969cfd4961ef8b2 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:50:14 -0800 Subject: [PATCH 06/50] 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 1c7817a2330..11e88567132 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -42,7 +42,7 @@ 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("D:\\MendRepo\\test-product\\test-project\\test-project-subcomponent\\path\\to\\the\\Java\\commons-codec-1.6_donotuse.jar", finding.steps_to_reproduce) 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: From 6ef3e1844d9b56206628c10f28e7692661f9f3b1 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:43:42 -0800 Subject: [PATCH 07/50] Refactoring this for SCA only and SAST will be an additional PR - need to restructure format slightly for SAST --- .../mend-platform-sast-many-findings.json | 831 ------------------ .../mend/mend-platform-sast-no-findings.json | 1 - .../mend/mend-platform-sast-one-finding.json | 167 ---- unittests/tools/test_mend_parser.py | 23 - 4 files changed, 1022 deletions(-) delete mode 100644 unittests/scans/mend/mend-platform-sast-many-findings.json delete mode 100644 unittests/scans/mend/mend-platform-sast-no-findings.json delete mode 100644 unittests/scans/mend/mend-platform-sast-one-finding.json diff --git a/unittests/scans/mend/mend-platform-sast-many-findings.json b/unittests/scans/mend/mend-platform-sast-many-findings.json deleted file mode 100644 index 3550e632cc3..00000000000 --- a/unittests/scans/mend/mend-platform-sast-many-findings.json +++ /dev/null @@ -1,831 +0,0 @@ -{ - 'response': [ - { - 'id': '4b132785-06ea-485e-b813-10911afc3130', - 'scanId': '4c5e09b2-756e-47b2-ab7c-c2de08de5580', - 'snapshotId': '4c1ddc4f-d08e-4fb6-a358-58d494a4d58e', - 'projectId': 'bc929188-8fe0-4a30-975e-86fcfcf6328f', - 'appId': '3a48010d-ae5a-42df-81c5-836271f64f9d', - 'type': { - 'id': 1, - 'commonId': 'path-traversal-22', - 'name': 'Path/Directory Traversal', - 'engineId': 5, - 'language': 'Ruby', - 'sarif': 'ruby-path-traversal', - 'sarifLevel': '', - 'order': 4, - 'severity': 'High', - 'severityRating': 7.913, - 'description': 'Path/Directory Traversal or file disclosure vulnerability occurs when an external input is used to construct a pathname that is intended to identify a file or a directory located underneath a restricted parent directory. The application does not properly neutralize (sanitize) special elements within the pathname, which can cause the pathname to resolve to a location that is outside of the restricted directory. Successful file disclosure attack can result in sensitive files disclosure, and can often lead to full system compromise', - 'recommendations': [ - 'Using a whitelist of directories from which files are allowed for download and validating requests based on that list', - 'Indexing files which are allowed for download and passing only their index numbers as the URL parameter values', - 'Validating requested file types' - ], - 'references': [ - 'https://owasp.org/www-community/attacks/Path_Traversal' - ], - 'cwe': { - 'id': 'CWE-22', - 'title': "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')", - 'url': 'https://cwe.mitre.org/data/definitions/22.html' - }, - 'pcidss': { - 'section': '6.5.8', - 'title': 'PCI DSS 6.5.8: Improper Access Control' - }, - 'nist': { - 'control': 'SI-10', - 'priority': 'P1', - 'title': 'SI-10: Information Input Validation', - 'url': 'https://nvd.nist.gov/800-53/Rev5/control/SI-10' - }, - 'hipaa': { - 'control': '164.312 (a)(1)', - 'title': '164.312 (a)(1): Standard: Access control' - }, - 'hitrust': { - 'control': '10.b', - 'title': '10.b: Input Data Validation (Level 1 Implementation)' - }, - 'owasp': { - 'index': 'A5', - 'title': 'A5: Broken Access Control', - 'url': 'https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A5-Broken_Access_Control' - }, - 'owasp2021': { - 'index': 'A1', - 'title': 'A1: Broken Access Control', - 'url': 'https://owasp.org/Top10/A01_2021-Broken_Access_Control/' - }, - 'capec': { - 'id': '126', - 'title': 'CAPEC-126: Path Traversal', - 'url': 'https://capec.mitre.org/data/definitions/126.html' - }, - 'sansTop25': { - 'rank': 8, - 'title': "CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" - } - }, - 'description': 'open() method could be abused to reveal sensitive file content and/or write to arbitrary files.', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'severity': 'High', - 'baseline': True, - 'hasRemediation': False, - 'suppressed': False, - 'suppressedBy': '', - 'suppressionTime': '0001-01-01T00:00:00Z', - 'suppressionMessage': '', - 'reviewed': False, - 'IssueStatus': 0, - 'sharedStep': { - 'name': 'File.open ', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'File.open(name, "w")', - 'line': 379, - 'startLine': 375, - 'endLine': 384, - 'lineBlame': { - 'commitId': '', - 'file': '', - 'line': 0 - } - }, - 'dataFlows': [ - { - 'id': 'dba3a480-5408-47cc-be6a-fab8dda52917', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'sink': 'File.open ', - 'sinkKind': '', - 'sinkFile': 'src/codegen/generate.rb', - 'sinkSnippet': 'File.open(name, "w")', - 'sinkLine': 379, - 'inputSource': 'ARGV', - 'inputKind': '', - 'inputFlow': [ - { - 'name': 'ARGV', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 394, - 'endLine': 403 - }, - { - 'name': 'destdir', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', - 'line': 317, - 'startLine': 313, - 'endLine': 322 - }, - { - 'name': 'name', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def create_folder_and_open(name)', - 'line': 377, - 'startLine': 373, - 'endLine': 382 - } - ], - 'functionCalls': [ - { - 'name': 'File.open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'File.open(name, "w")', - 'line': 379, - 'startLine': 375, - 'endLine': 384 - }, - { - 'name': 'create_folder_and_open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'f = create_folder_and_open("#{destdir}#{accservice}/dto/testModify.java")', - 'line': 346, - 'startLine': 0, - 'endLine': 0 - }, - { - 'name': 'generate_acc', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 0, - 'endLine': 0 - } - ], - 'filter': { - 'isFiltered': False, - 'filterTypes': [] - }, - 'rating': 6.307692307692308, - 'confidenceRating': 6, - 'ageRating': 8 - }, - { - 'id': '96c3eab0-d5ac-486b-9bbf-2ab5bb36ee10', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'sink': 'File.open ', - 'sinkKind': '', - 'sinkFile': 'src/codegen/generate.rb', - 'sinkSnippet': 'File.open(name, "w")', - 'sinkLine': 379, - 'inputSource': 'ARGV', - 'inputKind': '', - 'inputFlow': [ - { - 'name': 'ARGV', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 394, - 'endLine': 403 - }, - { - 'name': 'destdir', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', - 'line': 317, - 'startLine': 313, - 'endLine': 322 - }, - { - 'name': 'name', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def create_folder_and_open(name)', - 'line': 377, - 'startLine': 373, - 'endLine': 382 - } - ], - 'functionCalls': [ - { - 'name': 'File.open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'File.open(name, "w")', - 'line': 379, - 'startLine': 375, - 'endLine': 384 - }, - { - 'name': 'create_folder_and_open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'f = create_folder_and_open(destdir + testservice + "/dto/responses/" + filename)', - 'line': 341, - 'startLine': 0, - 'endLine': 0 - }, - { - 'name': 'generate_acc', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 0, - 'endLine': 0 - } - ], - 'filter': { - 'isFiltered': False, - 'filterTypes': [] - }, - 'rating': 6.307692307692308, - 'confidenceRating': 6, - 'ageRating': 8 - }, - { - 'id': '408f3055-c076-4330-8ecb-c9e4f657472a', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'sink': 'File.open ', - 'sinkKind': '', - 'sinkFile': 'src/codegen/generate.rb', - 'sinkSnippet': 'File.open(name, "w")', - 'sinkLine': 379, - 'inputSource': 'ARGV', - 'inputKind': '', - 'inputFlow': [ - { - 'name': 'ARGV', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 394, - 'endLine': 403 - }, - { - 'name': 'destdir', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', - 'line': 317, - 'startLine': 313, - 'endLine': 322 - }, - { - 'name': 'name', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def create_folder_and_open(name)', - 'line': 377, - 'startLine': 373, - 'endLine': 382 - } - ], - 'functionCalls': [ - { - 'name': 'File.open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'File.open(name, "w")', - 'line': 379, - 'startLine': 375, - 'endLine': 384 - }, - { - 'name': 'create_folder_and_open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'f = create_folder_and_open(destdir + testservice + "/dto/requests/" + filename)', - 'line': 334, - 'startLine': 0, - 'endLine': 0 - }, - { - 'name': 'generate_acc', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 0, - 'endLine': 0 - } - ], - 'filter': { - 'isFiltered': False, - 'filterTypes': [] - }, - 'rating': 6.307692307692308, - 'confidenceRating': 6, - 'ageRating': 8 - }, - { - 'id': 'f319f409-6021-40fd-8f0a-de36e52a93d9', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'sink': 'File.open ', - 'sinkKind': '', - 'sinkFile': 'src/codegen/generate.rb', - 'sinkSnippet': 'File.open(name, "w")', - 'sinkLine': 379, - 'inputSource': 'ARGV', - 'inputKind': '', - 'inputFlow': [ - { - 'name': 'ARGV', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 394, - 'endLine': 403 - }, - { - 'name': 'destdir', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', - 'line': 317, - 'startLine': 313, - 'endLine': 322 - }, - { - 'name': 'name', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def create_folder_and_open(name)', - 'line': 377, - 'startLine': 373, - 'endLine': 382 - } - ], - 'functionCalls': [ - { - 'name': 'File.open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'File.open(name, "w")', - 'line': 379, - 'startLine': 375, - 'endLine': 384 - }, - { - 'name': 'create_folder_and_open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'f = create_folder_and_open(destdir + testservice + "/impl/" + filename)', - 'line': 328, - 'startLine': 0, - 'endLine': 0 - }, - { - 'name': 'generate_acc', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 0, - 'endLine': 0 - } - ], - 'filter': { - 'isFiltered': False, - 'filterTypes': [] - }, - 'rating': 6.307692307692308, - 'confidenceRating': 6, - 'ageRating': 8 - }, - { - 'id': '4c376010-9ea8-4c99-84dc-994dab9baeac', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'sink': 'File.open ', - 'sinkKind': '', - 'sinkFile': 'src/codegen/generate.rb', - 'sinkSnippet': 'File.open(name, "w")', - 'sinkLine': 379, - 'inputSource': 'ARGV', - 'inputKind': '', - 'inputFlow': [ - { - 'name': 'ARGV', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 394, - 'endLine': 403 - }, - { - 'name': 'destdir', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def generate_acc(destdir, functions, types, pwmfunctions, pwmtypes, protocolversion)', - 'line': 317, - 'startLine': 313, - 'endLine': 322 - }, - { - 'name': 'name', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'def create_folder_and_open(name)', - 'line': 377, - 'startLine': 373, - 'endLine': 382 - } - ], - 'functionCalls': [ - { - 'name': 'File.open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'File.open(name, "w")', - 'line': 379, - 'startLine': 375, - 'endLine': 384 - }, - { - 'name': 'create_folder_and_open', - 'kind': '', - 'file': 'src/codegen/generate.rb', - 'snippet': 'f = create_folder_and_open(destdir + testservice + "/" + filename)', - 'line': 323, - 'startLine': 0, - 'endLine': 0 - }, - { - 'name': 'generate_acc', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': 'import com.foxt.acc.exception.LevelType;', - 'line': 398, - 'startLine': 0, - 'endLine': 0 - } - ], - 'filter': { - 'isFiltered': False, - 'filterTypes': [] - }, - 'rating': 6.307692307692308, - 'confidenceRating': 6, - 'ageRating': 8 - } - ], - 'severityRating': 7.913, - 'confidenceRating': 6, - 'ageRating': 0, - 'rating': 3.7982400000000003, - 'almIssues': { - 'jira': { - 'issueId': '', - 'project': '' - }, - 'azure': { - 'workItemId': 0, - 'project': '' - }, - 'jiraPlatform': { - 'internalStatus': '', - 'issueStatus': '', - 'issueKey': '', - 'publicLink': '', - 'createdTime': '0001-01-01T00:00:00Z', - 'createdBy': '', - 'createdByName': '' - } - }, - 'comments': [], - 'workflowViolationsCount': 0, - 'workflowViolations': [] - }, - { - 'id': '240f8300-fe4c-4602-83f7-656deec30222', - 'scanId': '4c5e09b2-756e-47b2-ab7c-c2de08de5580', - 'snapshotId': 'aed0bec0-2067-472f-aa84-66d2e7ef9b16', - 'projectId': 'bc929188-8fe0-4a30-975e-86fcfcf6328f', - 'appId': '3a48010d-ae5a-42df-81c5-836271f64f9d', - 'type': { - 'id': 10, - 'commonId': 'weak-hash-916', - 'name': 'Weak Hash Strength', - 'engineId': 5, - 'language': 'Ruby', - 'sarif': 'ruby-weak-hash', - 'sarifLevel': '', - 'order': 16, - 'severity': 'Low', - 'severityRating': 2.987, - 'description': 'The application generates a hash but it uses a scheme that does not provide a sufficient level of computational effort that would make cracking attacks infeasible or expensive', - 'recommendations': [ - 'Use an adaptive hash function that can be configured to change the amount of computational effort needed to compute the hash, such as the number of iterations ("stretching") or the amount of memory required. Some hash functions perform salting automatically. These functions can significantly increase the overhead for a brute force attack compared to intentionally-fast functions such as MD5' - ], - 'references': [ - 'https://www.owasp.org/index.php/Testing_for_Weak_Encryption_(OTG-CRYPST-004)' - ], - 'cwe': { - 'id': 'CWE-916', - 'title': 'CWE-916: Use of Password Hash With Insufficient Computational Effort', - 'url': 'https://cwe.mitre.org/data/definitions/916.html' - }, - 'pcidss': { - 'section': '6.5.3', - 'title': 'PCI DSS 6.5.3: Insecure Cryptographic Storage' - }, - 'nist': { - 'control': 'SC-13', - 'priority': 'P1', - 'title': 'SC-13: Cryptographic Protection', - 'url': 'https://nvd.nist.gov/800-53/Rev5/control/SC-13' - }, - 'hipaa': { - 'control': '164.312 (a)(2)(iv)', - 'title': '164.312 (a)(2)(iv): Access Control: Encryption and Decryption' - }, - 'hitrust': { - 'control': '', - 'title': '' - }, - 'owasp': { - 'index': 'A3', - 'title': 'A3: Sensitive Data Exposure', - 'url': 'https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A3-Sensitive_Data_Exposure' - }, - 'owasp2021': { - 'index': 'A2', - 'title': 'A2: Cryptographic Failures', - 'url': 'https://owasp.org/Top10/A02_2021-Cryptographic_Failures/' - }, - 'capec': { - 'id': '97', - 'title': 'CAPEC-97: Cryptanalysis', - 'url': 'https://capec.mitre.org/data/definitions/97.html' - }, - 'sansTop25': { - 'rank': 0, - 'title': '' - } - }, - 'description': 'It is not advised to use weak cryptographic function.', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'severity': 'Low', - 'baseline': True, - 'hasRemediation': False, - 'suppressed': False, - 'suppressedBy': '', - 'suppressionTime': '0001-01-01T00:00:00Z', - 'suppressionMessage': '', - 'reviewed': False, - 'IssueStatus': 0, - 'sharedStep': { - 'name': 'Weak cryptographic function ', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': "'sha512SaltLen'", - 'line': 141, - 'startLine': 137, - 'endLine': 146, - 'lineBlame': { - 'commitId': '', - 'file': '', - 'line': 0 - } - }, - 'dataFlows': [ - { - 'id': '2ec00687-01c6-48e0-8891-1f6f3b314438', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'sink': 'Weak cryptographic function ', - 'sinkKind': '', - 'sinkFile': 'src/codegen/acc_proto.rb', - 'sinkSnippet': "'sha512SaltLen'", - 'sinkLine': 141, - 'inputSource': 'Weak cryptographic function - sha', - 'inputKind': '', - 'inputFlow': [ - { - 'name': 'Weak cryptographic function', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': "'sha512SaltLen'", - 'line': 141, - 'startLine': 0, - 'endLine': 0 - } - ], - 'functionCalls': [ - { - 'name': 'Insecure cryptographic function', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': "'sha512SaltLen'", - 'line': 141, - 'startLine': 137, - 'endLine': 146 - } - ], - 'filter': { - 'isFiltered': False, - 'filterTypes': [] - }, - 'rating': 9.692307692307692, - 'confidenceRating': 10, - 'ageRating': 8 - } - ], - 'severityRating': 2.987, - 'confidenceRating': 10, - 'ageRating': 0, - 'rating': 2.3896, - 'almIssues': { - 'jira': { - 'issueId': '', - 'project': '' - }, - 'azure': { - 'workItemId': 0, - 'project': '' - }, - 'jiraPlatform': { - 'internalStatus': '', - 'issueStatus': '', - 'issueKey': '', - 'publicLink': '', - 'createdTime': '0001-01-01T00:00:00Z', - 'createdBy': '', - 'createdByName': '' - } - }, - 'comments': [], - 'workflowViolationsCount': 0, - 'workflowViolations': [] - }, - { - 'id': '2ca40933-ada9-436a-b021-8065f1352d45', - 'scanId': '4c5e09b2-756e-47b2-ab7c-c2de08de5580', - 'snapshotId': 'db2fd7d0-83c1-4c4d-8613-fa782328e78f', - 'projectId': 'bc929188-8fe0-4a30-975e-86fcfcf6328f', - 'appId': '3a48010d-ae5a-42df-81c5-836271f64f9d', - 'type': { - 'id': 10, - 'commonId': 'weak-hash-916', - 'name': 'Weak Hash Strength', - 'engineId': 5, - 'language': 'Ruby', - 'sarif': 'ruby-weak-hash', - 'sarifLevel': '', - 'order': 16, - 'severity': 'Low', - 'severityRating': 2.987, - 'description': 'The application generates a hash but it uses a scheme that does not provide a sufficient level of computational effort that would make cracking attacks infeasible or expensive', - 'recommendations': [ - 'Use an adaptive hash function that can be configured to change the amount of computational effort needed to compute the hash, such as the number of iterations ("stretching") or the amount of memory required. Some hash functions perform salting automatically. These functions can significantly increase the overhead for a brute force attack compared to intentionally-fast functions such as MD5' - ], - 'references': [ - 'https://www.owasp.org/index.php/Testing_for_Weak_Encryption_(OTG-CRYPST-004)' - ], - 'cwe': { - 'id': 'CWE-916', - 'title': 'CWE-916: Use of Password Hash With Insufficient Computational Effort', - 'url': 'https://cwe.mitre.org/data/definitions/916.html' - }, - 'pcidss': { - 'section': '6.5.3', - 'title': 'PCI DSS 6.5.3: Insecure Cryptographic Storage' - }, - 'nist': { - 'control': 'SC-13', - 'priority': 'P1', - 'title': 'SC-13: Cryptographic Protection', - 'url': 'https://nvd.nist.gov/800-53/Rev5/control/SC-13' - }, - 'hipaa': { - 'control': '164.312 (a)(2)(iv)', - 'title': '164.312 (a)(2)(iv): Access Control: Encryption and Decryption' - }, - 'hitrust': { - 'control': '', - 'title': '' - }, - 'owasp': { - 'index': 'A3', - 'title': 'A3: Sensitive Data Exposure', - 'url': 'https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A3-Sensitive_Data_Exposure' - }, - 'owasp2021': { - 'index': 'A2', - 'title': 'A2: Cryptographic Failures', - 'url': 'https://owasp.org/Top10/A02_2021-Cryptographic_Failures/' - }, - 'capec': { - 'id': '97', - 'title': 'CAPEC-97: Cryptanalysis', - 'url': 'https://capec.mitre.org/data/definitions/97.html' - }, - 'sansTop25': { - 'rank': 0, - 'title': '' - } - }, - 'description': 'It is not advised to use weak cryptographic function.', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'severity': 'Low', - 'baseline': True, - 'hasRemediation': False, - 'suppressed': False, - 'suppressedBy': '', - 'suppressionTime': '0001-01-01T00:00:00Z', - 'suppressionMessage': '', - 'reviewed': False, - 'IssueStatus': 0, - 'sharedStep': { - 'name': 'Weak cryptographic function ', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': "'sha512Rounds',", - 'line': 140, - 'startLine': 136, - 'endLine': 145, - 'lineBlame': { - 'commitId': '', - 'file': '', - 'line': 0 - } - }, - 'dataFlows': [ - { - 'id': '2a3cd60d-2579-4557-889e-f43855f44ba5', - 'createdTime': '2024-08-08T06:27:38.811Z', - 'sink': 'Weak cryptographic function ', - 'sinkKind': '', - 'sinkFile': 'src/codegen/acc_proto.rb', - 'sinkSnippet': "'sha512Rounds',", - 'sinkLine': 140, - 'inputSource': 'Weak cryptographic function - sha', - 'inputKind': '', - 'inputFlow': [ - { - 'name': 'Weak cryptographic function', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': "'sha512Rounds',", - 'line': 140, - 'startLine': 0, - 'endLine': 0 - } - ], - 'functionCalls': [ - { - 'name': 'Insecure cryptographic function', - 'kind': '', - 'file': 'src/codegen/acc_proto.rb', - 'snippet': "'sha512Rounds',", - 'line': 140, - 'startLine': 136, - 'endLine': 145 - } - ], - 'filter': { - 'isFiltered': False, - 'filterTypes': [] - }, - 'rating': 9.692307692307692, - 'confidenceRating': 10, - 'ageRating': 8 - } - ], - 'severityRating': 2.987, - 'confidenceRating': 10, - 'ageRating': 0, - 'rating': 2.3896, - 'almIssues': { - 'jira': { - 'issueId': '', - 'project': '' - }, - 'azure': { - 'workItemId': 0, - 'project': '' - }, - 'jiraPlatform': { - 'internalStatus': '', - 'issueStatus': '', - 'issueKey': '', - 'publicLink': '', - 'createdTime': '0001-01-01T00:00:00Z', - 'createdBy': '', - 'createdByName': '' - } - }, - 'comments': [], - 'workflowViolationsCount': 0, - 'workflowViolations': [] - } - ], - 'additionalData': None, - 'supportToken': 'b2f7a762258bbe6b842c1b6fccd75eb9756e84f0d3973058' -} \ No newline at end of file diff --git a/unittests/scans/mend/mend-platform-sast-no-findings.json b/unittests/scans/mend/mend-platform-sast-no-findings.json deleted file mode 100644 index cf31cbe997d..00000000000 --- a/unittests/scans/mend/mend-platform-sast-no-findings.json +++ /dev/null @@ -1 +0,0 @@ -{'response': [], 'additionalData': None, 'supportToken': '12345fca9ac7329360d302ce711c84eb3917a06c9747f7b7'} \ No newline at end of file diff --git a/unittests/scans/mend/mend-platform-sast-one-finding.json b/unittests/scans/mend/mend-platform-sast-one-finding.json deleted file mode 100644 index 2e59a8f0e92..00000000000 --- a/unittests/scans/mend/mend-platform-sast-one-finding.json +++ /dev/null @@ -1,167 +0,0 @@ -{ - 'response': [ - { - 'id': '42f09f21-7e77-45bb-9af0-1750b9664faf', - 'scanId': 'b5e748b4-a6ff-4303-89a6-b051062fa5e3', - 'snapshotId': 'e84dc715-b34e-43ba-8ad3-ff9303dcff54', - 'projectId': '4a84dc99-256b-460f-8af3-7e33ad9e8f00', - 'appId': 'd3faf1a5-65b5-4817-a6dc-c6862faebd63', - 'type': { - 'id': 55, - 'commonId': 'crypto-missing-step-325', - 'name': 'Missing Cryptographic Step', - 'engineId': 101, - 'language': 'Java*', - 'sarif': 'java-crypto-missing-step', - 'sarifLevel': '', - 'order': 35, - 'severity': 'Low', - 'severityRating': 2.143, - 'description': 'The application does not implement or incorrectly implements a necessary step in a cryptographic process. Such omission or error can lead to security vulnerabilities and weaken the overall effectiveness of the cryptographic process', - 'recommendations': [ - 'Check if all the necessary steps for a cryptographic process have been implemented' - ], - 'references': [ - 'https://cwe.mitre.org/data/definitions/325.html' - ], - 'cwe': { - 'id': 'CWE-325', - 'title': 'CWE-325: Missing Cryptographic Step', - 'url': 'https://cwe.mitre.org/data/definitions/325.html' - }, - 'pcidss': { - 'section': '6.5.3', - 'title': 'PCI DSS 6.5.3: Insecure Cryptographic Storage' - }, - 'nist': { - 'control': 'SC-13', - 'priority': 'P1', - 'title': 'SC-13: Cryptographic Protection', - 'url': 'https://nvd.nist.gov/800-53/Rev5/control/SC-13' - }, - 'hipaa': { - 'control': '164.312 (a)(2)(iv)', - 'title': '164.312 (a)(2)(iv): Access Control: Encryption and Decryption' - }, - 'hitrust': { - 'control': '', - 'title': '' - }, - 'owasp': { - 'index': 'A3', - 'title': 'A3: Sensitive Data Exposure', - 'url': 'https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure' - }, - 'owasp2021': { - 'index': 'A2', - 'title': 'A2: Cryptographic Failures', - 'url': 'https://owasp.org/Top10/A02_2021-Cryptographic_Failures/' - }, - 'capec': { - 'id': '97', - 'title': 'CAPEC-97: Cryptanalysis', - 'url': 'https://capec.mitre.org/data/definitions/97.html' - }, - 'sansTop25': { - 'rank': 0, - 'title': '' - } - }, - 'description': "'init' method of 'javax.crypto.KeyGenerator' uses a crypto algorithm in a wrong way. Key size is not valid", - 'createdTime': '2024-08-12T06:37:37.336Z', - 'severity': 'Low', - 'baseline': True, - 'hasRemediation': False, - 'suppressed': False, - 'suppressedBy': '', - 'suppressionTime': '0001-01-01T00:00:00Z', - 'suppressionMessage': '', - 'reviewed': False, - 'IssueStatus': 0, - 'sharedStep': { - 'name': 'javax.crypto.KeyGenerator.init', - 'kind': '', - 'file': 'src/com/foxt/password/PasswordCryptFile.java', - 'snippet': 'kg.init(klen);', - 'line': 145, - 'startLine': 141, - 'endLine': 150, - 'lineBlame': { - 'commitId': '', - 'file': '', - 'line': 0 - } - }, - 'dataFlows': [ - { - 'id': 'cfab7e98-23fb-4028-8f12-36c69355ec5c', - 'createdTime': '2024-08-12T06:37:37.336Z', - 'sink': 'javax.crypto.KeyGenerator.init', - 'sinkKind': '', - 'sinkFile': 'src/com/foxt/password/PasswordCryptFile.java', - 'sinkSnippet': 'kg.init(klen);', - 'sinkLine': 145, - 'inputSource': 'kg', - 'inputKind': 'variable', - 'inputFlow': [ - { - 'name': 'kg', - 'kind': 'variable', - 'file': 'src/com/foxt/password/PasswordCryptFile.java', - 'snippet': 'KeyGenerator kg = KeyGenerator.getInstance(s_algorithm);', - 'line': 139, - 'startLine': 135, - 'endLine': 144 - } - ], - 'functionCalls': [ - { - 'name': 'javax.crypto.KeyGenerator.init', - 'kind': '', - 'file': 'src/com/foxt/password/PasswordCryptFile.java', - 'snippet': 'kg.init(klen);', - 'line': 145, - 'startLine': 141, - 'endLine': 150 - } - ], - 'filter': { - 'isFiltered': False, - 'filterTypes': [] - }, - 'rating': 9.692307692307692, - 'confidenceRating': 10, - 'ageRating': 8 - } - ], - 'severityRating': 2.143, - 'confidenceRating': 10, - 'ageRating': 0, - 'rating': 1.7144, - 'almIssues': { - 'jira': { - 'issueId': '', - 'project': '' - }, - 'azure': { - 'workItemId': 0, - 'project': '' - }, - 'jiraPlatform': { - 'internalStatus': '', - 'issueStatus': '', - 'issueKey': '', - 'publicLink': '', - 'createdTime': '0001-01-01T00:00:00Z', - 'createdBy': '', - 'createdByName': '' - } - }, - 'comments': [], - 'workflowViolationsCount': 0, - 'workflowViolations': [] - } - ], - 'additionalData': None, - 'supportToken': '4ca13f5d1a546e16da5e518408ea99ac6dc3b2d245aceff6' -} \ No newline at end of file diff --git a/unittests/tools/test_mend_parser.py b/unittests/tools/test_mend_parser.py index 11e88567132..bd5abed0c8d 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -66,26 +66,3 @@ def test_parse_file_with_multiple_vuln_has_multiple_finding_platform(self): parser = MendParser() findings = parser.get_findings(testfile, Test()) self.assertEqual(11, len(findings)) - - def test_parse_file_with_no_vuln_has_no_findings_platform_sast(self): - with open("unittests/scans/mend/mend-platform-sast-no-findings.json", encoding="utf-8") as testfile: - parser = MendParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) - - def test_parse_file_with_one_vuln_has_one_findings_platform_sast(self): - with open("unittests/scans/mend/mend-platform-sast-one-finding.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(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CWE-325", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("10", finding.cvssv3) - self.assertEqual(2.143, finding.cvssv3_score) - - def test_parse_file_with_multiple_vuln_has_multiple_finding_platform_sast(self): - with open("unittests/scans/mend/mend-platform-sast-many-findings.json", encoding="utf-8") as testfile: - parser = MendParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) From bee60ea607806fc33589245960b8bcfe8ec3b73b Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:59:36 -0800 Subject: [PATCH 08/50] Update parser.py --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index fde27c187e0..9909569aa0c 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -187,7 +187,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce=steps_to_reproduce if steps_to_reproduce is not None else None, + steps_to_reproduce=", ".join(locations) if locations is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From 893edc97757fc217f09647bf2f62d4dac5aa8ec7 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:00:40 -0800 Subject: [PATCH 09/50] Update parser.py --- dojo/tools/mend/parser.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 9909569aa0c..53785d602ec 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -170,7 +170,6 @@ def _build_common_output(node, lib_name=None): ) filepaths = filepaths - steps_to_reproduce = locations new_finding = Finding( title=title, From 128698dfd601e049a94f7de91817b72fd93ce7cc Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:03:54 -0800 Subject: [PATCH 10/50] Update parser.py --- dojo/tools/mend/parser.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 53785d602ec..3327eff2b8f 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -168,6 +168,9 @@ def _build_common_output(node, lib_name=None): logger.exception( "Error handling local paths for vulnerability.", ) + if locations and len(", ".join(locations)) > 3999: + locations = [loc[:399] for loc in locations] + locations = ", ".join(locations)[:3999] filepaths = filepaths From 9290faeb80f6820d1f516621e7b1e9ec1f22fbe9 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:55:09 -0800 Subject: [PATCH 11/50] fix loc 399 to 3999 for locations + add steps_to_reproduce for SCA Platform similar to SCA Legacy so Findings can be structured similarly --- dojo/tools/mend/parser.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 3327eff2b8f..e6907062a9a 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" + steps_to_reproduce = None if "component" in node: description = ( "**Vulnerability Description**: " @@ -65,6 +66,7 @@ def _build_common_output(node, lib_name=None): component_version = node["component"].get("version") impact = node["component"].get("dependencyType") cvss3_score = node["vulnerability"].get("score", None) + steps_to_reproduce = node["component"].get("path", None) if "topFix" in node: try: topfix_node = node.get("topFix") @@ -169,8 +171,9 @@ def _build_common_output(node, lib_name=None): "Error handling local paths for vulnerability.", ) if locations and len(", ".join(locations)) > 3999: - locations = [loc[:399] for loc in locations] + locations = [loc[:3999] for loc in locations] locations = ", ".join(locations)[:3999] + steps_to_reproduce=", ".join(locations) if locations is not None else None, filepaths = filepaths @@ -189,7 +192,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce=", ".join(locations) if locations is not None else None, + steps_to_reproduce=steps_to_reproduce if steps_to_reproduce is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From 99323d613b834e6c6d8fdae7c99894fa24506815 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:56:15 -0800 Subject: [PATCH 12/50] Fix spacing, remove trailing comma --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index e6907062a9a..bc2654b0725 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -173,7 +173,7 @@ def _build_common_output(node, lib_name=None): if locations and len(", ".join(locations)) > 3999: locations = [loc[:3999] for loc in locations] locations = ", ".join(locations)[:3999] - steps_to_reproduce=", ".join(locations) if locations is not None else None, + steps_to_reproduce= ", ".join(locations) if locations is not None else None filepaths = filepaths From 34d83645e666138ad9665fe28e0c91e9d7f89e6d Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:57:15 -0800 Subject: [PATCH 13/50] Fix space --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index bc2654b0725..e2e26a7ac69 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -173,7 +173,7 @@ def _build_common_output(node, lib_name=None): if locations and len(", ".join(locations)) > 3999: locations = [loc[:3999] for loc in locations] locations = ", ".join(locations)[:3999] - steps_to_reproduce= ", ".join(locations) if locations is not None else None + steps_to_reproduce = ", ".join(locations) if locations is not None else None filepaths = filepaths From 9d50ad5e4edc9ee992fc0d408d6c087ce9470fa2 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 10:08:29 -0800 Subject: [PATCH 14/50] Removing redundancy --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index e2e26a7ac69..56cec6f1dab 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -66,7 +66,7 @@ def _build_common_output(node, lib_name=None): component_version = node["component"].get("version") impact = node["component"].get("dependencyType") cvss3_score = node["vulnerability"].get("score", None) - steps_to_reproduce = node["component"].get("path", None) + steps_to_reproduce = node["component"].get("path") if "topFix" in node: try: topfix_node = node.get("topFix") From 122fbbcf8e8175fe7ccb349ea4d5fa49280282c9 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 10:30:45 -0800 Subject: [PATCH 15/50] Fix the join on locations for Platform SCA --- dojo/tools/mend/parser.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 56cec6f1dab..3975a537a04 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -39,7 +39,7 @@ def _build_common_output(node, lib_name=None): description = "No Description Available" cvss3_score = None mitigation = "N/A" - steps_to_reproduce = None + locations = [] if "component" in node: description = ( "**Vulnerability Description**: " @@ -66,7 +66,10 @@ def _build_common_output(node, lib_name=None): component_version = node["component"].get("version") impact = node["component"].get("dependencyType") cvss3_score = node["vulnerability"].get("score", None) - steps_to_reproduce = node["component"].get("path") + component_path = node["component"].get("path", None) + if component_path: + locations.append(component_path) + if "topFix" in node: try: topfix_node = node.get("topFix") @@ -158,7 +161,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", []) @@ -173,7 +175,6 @@ def _build_common_output(node, lib_name=None): if locations and len(", ".join(locations)) > 3999: locations = [loc[:3999] for loc in locations] locations = ", ".join(locations)[:3999] - steps_to_reproduce = ", ".join(locations) if locations is not None else None filepaths = filepaths @@ -192,7 +193,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce=steps_to_reproduce if steps_to_reproduce is not None else None, + steps_to_reproduce=", ".join(locations) if locations is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From 9ab5fbbe2cb6512fe5572238456fd2bb0b19c1cf Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 11:05:45 -0800 Subject: [PATCH 16/50] Removing redundancy component dependency type from description since it's in impact as well Removing redundancy component dependency type from description since it's in impact as well --- dojo/tools/mend/parser.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 3975a537a04..478dbbcfe75 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -57,9 +57,6 @@ def _build_common_output(node, lib_name=None): + "**Library Type**: " + node["component"].get("libraryType", "") + "\n" - + "**Direct or Transitive Dependency**: " - + node["component"].get("dependencyType", "") - + "\n" ) lib_name = node["component"].get("name") component_name = node["component"].get("artifactId") From f17973273b400eafe064ae9885a6331e430abd7e Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 11:12:10 -0800 Subject: [PATCH 17/50] Make Impact more readible --- dojo/tools/mend/parser.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 478dbbcfe75..f09ebc988c9 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -61,7 +61,11 @@ def _build_common_output(node, lib_name=None): 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: From 866ec7a8cc6fb669e92b55dd3cd0c3dafd6c744a Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 11:14:52 -0800 Subject: [PATCH 18/50] Update parser.py --- dojo/tools/mend/parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index f09ebc988c9..b976edccab4 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -64,7 +64,7 @@ def _build_common_output(node, lib_name=None): impact = ( "**Direct or Transitive Vulnerability**: " + node["component"].get("dependencyType") - +"\n" + + "\n" ) cvss3_score = node["vulnerability"].get("score", None) component_path = node["component"].get("path", None) @@ -194,7 +194,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce=", ".join(locations) if locations 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] From 3e0e95fe063d71e34825ff9f1f19ee64267185a7 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 11:16:38 -0800 Subject: [PATCH 19/50] Update format for unit test --- 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 bd5abed0c8d..e4759718cd6 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -42,7 +42,7 @@ 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.steps_to_reproduce) + 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) 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: From 1357de49a18c08da3c343fea924472b202e9cf9a Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Tue, 10 Dec 2024 11:46:04 -0800 Subject: [PATCH 20/50] Fix case on unit test --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index b976edccab4..112833db5cb 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -194,7 +194,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce="**Locations found**: " + ", ".join(locations) if locations 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] From ff0725c372724b488fa45617f751cd4060cae7d2 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:11:58 -0800 Subject: [PATCH 21/50] Remove duplicate join to fix steps_to_reproduce formatting Remove duplicate join to fix steps_to_reproduce formatting --- dojo/tools/mend/parser.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 112833db5cb..c5cc48b456a 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -173,9 +173,16 @@ def _build_common_output(node, lib_name=None): logger.exception( "Error handling local paths for vulnerability.", ) - if locations and len(", ".join(locations)) > 3999: - locations = [loc[:3999] for loc in locations] - locations = ", ".join(locations)[:3999] + if locations: + if len(", ".join(locations)) > 3999: + locations = [loc[:3999] for loc in locations] + locations_str = ", ".join(locations)[:3999] + else: + locations_str = ", ".join(locations) + + steps_to_reproduce = "**Locations Found**: " + locations_str + else: + steps_to_reproduce = None filepaths = filepaths @@ -194,7 +201,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce="**Locations Found**: " + ", ".join(locations) if locations is not None else None, + steps_to_reproduce=steps_to_reproduce, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From d4ac0e281d2f9cc8a5caa738ae59875138a22fc2 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:57:07 -0800 Subject: [PATCH 22/50] Fix join for locations and steps_to_reproduce --- dojo/tools/mend/parser.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index c5cc48b456a..79af88ec64c 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -70,6 +70,7 @@ def _build_common_output(node, lib_name=None): component_path = node["component"].get("path", None) if component_path: locations.append(component_path) + steps_to_reproduce = locations if "topFix" in node: try: @@ -173,16 +174,12 @@ def _build_common_output(node, lib_name=None): logger.exception( "Error handling local paths for vulnerability.", ) - if locations: - if len(", ".join(locations)) > 3999: - locations = [loc[:3999] for loc in locations] - locations_str = ", ".join(locations)[:3999] - else: - locations_str = ", ".join(locations) - - steps_to_reproduce = "**Locations Found**: " + locations_str + if locations and len(", ".join(locations)) > 3999: + locations = [loc[:3999] for loc in locations] + locations = ", ".join(locations)[:3999] + steps_to_reproduce = "**Locations Found**: " + locations if locations is not None else None else: - steps_to_reproduce = None + steps_to_reproduce = ", ".join(locations) filepaths = filepaths @@ -201,7 +198,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce=steps_to_reproduce, + steps_to_reproduce=steps_to_reproduce if steps_to_reproduce is not None else None ) if cve: new_finding.unsaved_vulnerability_ids = [cve] @@ -266,4 +263,4 @@ def create_finding_key(f: Finding) -> str: if dupe_key not in dupes: dupes[dupe_key] = finding - return list(dupes.values()) + return list(dupes.values()) \ No newline at end of file From 51e71821e83d2554afd99c77ae79caf123cddde0 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:58:17 -0800 Subject: [PATCH 23/50] fix newline eof --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 79af88ec64c..0fc4b60545f 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -263,4 +263,4 @@ def create_finding_key(f: Finding) -> str: if dupe_key not in dupes: dupes[dupe_key] = finding - return list(dupes.values()) \ No newline at end of file + return list(dupes.values()) From a1151e9b01d095af4926c14bb34b2e21459cdb35 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:59:57 -0800 Subject: [PATCH 24/50] fix comma, remove redundant locations reference --- dojo/tools/mend/parser.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 0fc4b60545f..95b4c45b9d2 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -70,7 +70,6 @@ def _build_common_output(node, lib_name=None): component_path = node["component"].get("path", None) if component_path: locations.append(component_path) - steps_to_reproduce = locations if "topFix" in node: try: @@ -198,7 +197,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce=steps_to_reproduce if steps_to_reproduce is not None else None + steps_to_reproduce=steps_to_reproduce if steps_to_reproduce is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From bc98f5de64f6e273bc27bc7581f7b794b207f97d Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:27:30 -0800 Subject: [PATCH 25/50] Update parser.py --- dojo/tools/mend/parser.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 95b4c45b9d2..514154a66ee 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -176,9 +176,6 @@ def _build_common_output(node, lib_name=None): if locations and len(", ".join(locations)) > 3999: locations = [loc[:3999] for loc in locations] locations = ", ".join(locations)[:3999] - steps_to_reproduce = "**Locations Found**: " + locations if locations is not None else None - else: - steps_to_reproduce = ", ".join(locations) filepaths = filepaths @@ -197,7 +194,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce=steps_to_reproduce if steps_to_reproduce is not None else None, + steps_to_reproduce="**Locations Found**: " + locations if locations is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] @@ -262,4 +259,4 @@ def create_finding_key(f: Finding) -> str: if dupe_key not in dupes: dupes[dupe_key] = finding - return list(dupes.values()) + return list(dupes.values()) \ No newline at end of file From 104e452de50aa265ffe950ae5ddbb96ce410d8f2 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:28:18 -0800 Subject: [PATCH 26/50] Fix eof --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 514154a66ee..911c77524a3 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -259,4 +259,4 @@ def create_finding_key(f: Finding) -> str: if dupe_key not in dupes: dupes[dupe_key] = finding - return list(dupes.values()) \ No newline at end of file + return list(dupes.values()) From 46cb93616bb1fb1af04c6b39620f8f1e4761da40 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:47:04 -0800 Subject: [PATCH 27/50] Update parser.py --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 911c77524a3..fad05557ebe 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -194,7 +194,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce="**Locations Found**: " + locations if locations is not None else None, + steps_to_reproduce="**Locations Found**: " locations if locations is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From 5ecc580c83b490231e03c7b900f84b52399ec30c Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:49:25 -0800 Subject: [PATCH 28/50] fix , --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index fad05557ebe..0ad52a1b241 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -194,7 +194,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce="**Locations Found**: " locations if locations is not None else None, + steps_to_reproduce="**Locations Found**: ", locations if locations is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From 0b8b2c3b298935be11196984842a8525b06e48ad Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:54:03 -0800 Subject: [PATCH 29/50] Update parser.py --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 0ad52a1b241..1673c353b03 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -194,7 +194,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce="**Locations Found**: ", locations if locations is not None else None, + steps_to_reproduce="**Locations Found**: ".get(locations) if locations is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From 582e7aae1a359d2f3be95e82adc538c8653fb5ad Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 17:06:50 -0800 Subject: [PATCH 30/50] Update parser.py --- dojo/tools/mend/parser.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 1673c353b03..5009f3b2fee 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -70,6 +70,7 @@ def _build_common_output(node, lib_name=None): component_path = node["component"].get("path", None) if component_path: locations.append(component_path) + steps_to_reproduce = "**Locations Found**: " + locations if locations is not None else None if "topFix" in node: try: @@ -176,6 +177,9 @@ def _build_common_output(node, lib_name=None): if locations and len(", ".join(locations)) > 3999: locations = [loc[:3999] for loc in locations] locations = ", ".join(locations)[:3999] + steps_to_reproduce = "**Locations Found**: " + locations if locations is not None else None + else: + steps_to_reproduce = ", ".join(locations) filepaths = filepaths @@ -194,7 +198,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce="**Locations Found**: ".get(locations) if locations is not None else None, + steps_to_reproduce=steps_to_reproduce if steps_to_reproduce is not None else None, ) if cve: new_finding.unsaved_vulnerability_ids = [cve] From b8c8e644fa86218ced8e91b7bd61d9986b4bf1fe Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 17:53:50 -0800 Subject: [PATCH 31/50] edit steps_to_reproduce locations found --- dojo/tools/mend/parser.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 5009f3b2fee..1af57d24a01 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -70,7 +70,6 @@ def _build_common_output(node, lib_name=None): component_path = node["component"].get("path", None) if component_path: locations.append(component_path) - steps_to_reproduce = "**Locations Found**: " + locations if locations is not None else None if "topFix" in node: try: @@ -176,10 +175,7 @@ def _build_common_output(node, lib_name=None): ) if locations and len(", ".join(locations)) > 3999: locations = [loc[:3999] for loc in locations] - locations = ", ".join(locations)[:3999] - steps_to_reproduce = "**Locations Found**: " + locations if locations is not None else None - else: - steps_to_reproduce = ", ".join(locations) + steps_to_reproduce = "**Locations Found**: " + ", ".join(locations) if locations is not None else None filepaths = filepaths From dd3cf09e48078a9ec815920c3c883216bec92459 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 11 Dec 2024 18:16:15 -0800 Subject: [PATCH 32/50] Update parser.py --- dojo/tools/mend/parser.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 1af57d24a01..04005317168 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -175,7 +175,6 @@ def _build_common_output(node, lib_name=None): ) if locations and len(", ".join(locations)) > 3999: locations = [loc[:3999] for loc in locations] - steps_to_reproduce = "**Locations Found**: " + ", ".join(locations) if locations is not None else None filepaths = filepaths @@ -194,7 +193,7 @@ def _build_common_output(node, lib_name=None): cvssv3=cvss3_vector, cvssv3_score=float(cvss3_score) if cvss3_score is not None else None, impact=impact, - steps_to_reproduce=steps_to_reproduce if steps_to_reproduce 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] From a472fac2e482d5e96dc901372273b20c8871be2a Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:09:11 -0800 Subject: [PATCH 33/50] fix 500 internal server error bug, add else None to impact for edge case --- dojo/tools/mend/parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 04005317168..0d85539d72d 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -63,7 +63,7 @@ def _build_common_output(node, lib_name=None): component_version = node["component"].get("version") impact = ( "**Direct or Transitive Vulnerability**: " - + node["component"].get("dependencyType") + + node["component"].get("dependencyType", "") + "\n" ) cvss3_score = node["vulnerability"].get("score", None) @@ -192,7 +192,7 @@ 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 is impact is not None else None, steps_to_reproduce="**Locations Found**: " + ", ".join(locations) if locations is not None else None, ) if cve: From 7e5fe444027cd6cf342e2b105ef0be9b9aada2d8 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:10:28 -0800 Subject: [PATCH 34/50] fix typo --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 0d85539d72d..5531394e9a7 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -192,7 +192,7 @@ 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 is impact is not None else None, + 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: From 7042699a5132c813fe82fe854d85bf5ac3af2e0e Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 20 Dec 2024 09:38:15 -0800 Subject: [PATCH 35/50] adding cneil suggestion for truncating locations adding cneil suggestion for truncating locations --- dojo/tools/mend/parser.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 5531394e9a7..ba98e980fce 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -173,8 +173,29 @@ def _build_common_output(node, lib_name=None): logger.exception( "Error handling local paths for vulnerability.", ) - if locations and len(", ".join(locations)) > 3999: - locations = [loc[:3999] for loc in locations] + 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 = filepaths From 34ab7143eaa28cf1bca01339e9c236cafc880891 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 20 Dec 2024 21:55:47 -0800 Subject: [PATCH 36/50] implement suggestion from Mend engineers --- dojo/tools/mend/parser.py | 95 ++++++++----------- ...-sca-platform-api3-multiple-findings.json} | 0 unittests/tools/test_mend_parser.py | 4 +- 3 files changed, 44 insertions(+), 55 deletions(-) rename unittests/scans/mend/{mend-sca-platform-api3-eleven-findings.json => mend-sca-platform-api3-multiple-findings.json} (100%) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index ba98e980fce..b94648a18f8 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -8,7 +8,6 @@ logger = logging.getLogger(__name__) - class MendParser: def get_scan_types(self): return ["Mend Scan"] @@ -41,51 +40,53 @@ def _build_common_output(node, lib_name=None): mitigation = "N/A" locations = [] if "component" in node: - description = ( - "**Vulnerability Description**: " - + node["vulnerability"].get("description", "No Description Available") - + "\n\n" - + "**Component Name**: " - + node["component"].get("name", "") - + "\n" - + "**Component Type**: " - + node["component"].get("componentType", "") - + "\n" - + "**Root Library**: " - + str(node["component"].get("rootLibrary", "")) - + "\n" - + "**Library Type**: " - + node["component"].get("libraryType", "") - + "\n" - ) - lib_name = node["component"].get("name") - component_name = node["component"].get("artifactId") - component_version = node["component"].get("version") - 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") - mitigation = ( - "**Resolution**: " - + topfix_node.get("date", "") + # Iterate over all findingInfo nodes and process each ACTIVE status + for finding_info in node.get("findingInfo", []): + if finding_info.get("status") == "ACTIVE": + description = ( + "**Vulnerability Description**: " + + node["vulnerability"].get("description", "No Description Available") + + "\n\n" + + "**Component Name**: " + + node["component"].get("name", "") + + "\n" + + "**Component Type**: " + + node["component"].get("componentType", "") + "\n" - + topfix_node.get("message", "") + + "**Root Library**: " + + str(node["component"].get("rootLibrary", "")) + "\n" - + topfix_node.get("fixResolution", "") + + "**Library Type**: " + + node["component"].get("libraryType", "") + "\n" ) - except Exception: - logger.exception("Error handling topFix node.") + lib_name = node["component"].get("name") + component_name = node["component"].get("artifactId") + component_version = node["component"].get("version") + 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") + mitigation = ( + "**Resolution**: " + + topfix_node.get("date", "") + + "\n" + + topfix_node.get("message", "") + + "\n" + + topfix_node.get("fixResolution", "") + + "\n" + ) + except Exception: + logger.exception("Error handling topFix node.") elif "library" in node: node.get("project") description = ( @@ -139,18 +140,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: 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 e4759718cd6..b68f51efc58 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -62,7 +62,7 @@ def test_parse_file_with_one_vuln_has_one_findings_platform(self): self.assertEqual(3.1, finding.cvssv3_score) 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)) From df287f7a39e49ff52ef65a4c5076270df6790ba7 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 20 Dec 2024 21:56:55 -0800 Subject: [PATCH 37/50] fix new line --- dojo/tools/mend/parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index b94648a18f8..f525cf3a3ae 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -8,6 +8,7 @@ logger = logging.getLogger(__name__) + class MendParser: def get_scan_types(self): return ["Mend Scan"] From 7a935fe2cda9f2f4ee4aefa20090e06d35d42e2a Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:15:38 -0800 Subject: [PATCH 38/50] Update parser.py --- dojo/tools/mend/parser.py | 92 +++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index f525cf3a3ae..fa39f6f0cfc 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -40,54 +40,50 @@ def _build_common_output(node, lib_name=None): cvss3_score = None mitigation = "N/A" locations = [] - if "component" in node: - # Iterate over all findingInfo nodes and process each ACTIVE status - for finding_info in node.get("findingInfo", []): - if finding_info.get("status") == "ACTIVE": - description = ( - "**Vulnerability Description**: " - + node["vulnerability"].get("description", "No Description Available") - + "\n\n" - + "**Component Name**: " - + node["component"].get("name", "") - + "\n" - + "**Component Type**: " - + node["component"].get("componentType", "") - + "\n" - + "**Root Library**: " - + str(node["component"].get("rootLibrary", "")) - + "\n" - + "**Library Type**: " - + node["component"].get("libraryType", "") - + "\n" - ) - lib_name = node["component"].get("name") - component_name = node["component"].get("artifactId") - component_version = node["component"].get("version") - 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") - mitigation = ( - "**Resolution**: " - + topfix_node.get("date", "") - + "\n" - + topfix_node.get("message", "") - + "\n" - + topfix_node.get("fixResolution", "") - + "\n" - ) - except Exception: - logger.exception("Error handling topFix node.") + if "component" in node and if finding_info.get("status") == "ACTIVE": + description = ( + "**Vulnerability Description**: " + + node["vulnerability"].get("description", "No Description Available") + + "\n\n" + + "**Component Name**: " + + node["component"].get("name", "") + + "\n" + + "**Component Type**: " + + node["component"].get("componentType", "") + + "\n" + + "**Root Library**: " + + str(node["component"].get("rootLibrary", "")) + + "\n" + + "**Library Type**: " + + node["component"].get("libraryType", "") + + "\n" + ) + lib_name = node["component"].get("name") + component_name = node["component"].get("artifactId") + component_version = node["component"].get("version") + 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") + mitigation = ( + "**Resolution**: " + + topfix_node.get("date", "") + + "\n" + + topfix_node.get("message", "") + + "\n" + + topfix_node.get("fixResolution", "") + + "\n" + ) + except Exception: + logger.exception("Error handling topFix node.") elif "library" in node: node.get("project") description = ( From 7eda867dbe347d012e47c2e5950fe1fa64988d91 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:16:30 -0800 Subject: [PATCH 39/50] Update parser.py --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index fa39f6f0cfc..d10ace729dc 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -40,7 +40,7 @@ def _build_common_output(node, lib_name=None): cvss3_score = None mitigation = "N/A" locations = [] - if "component" in node and if finding_info.get("status") == "ACTIVE": + if "component" in node and finding_info.get("status") == "ACTIVE": description = ( "**Vulnerability Description**: " + node["vulnerability"].get("description", "No Description Available") From 21f1bfab1a8a2a0170306e1d1ef7273dd08052e7 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:18:51 -0800 Subject: [PATCH 40/50] fix indentation --- dojo/tools/mend/parser.py | 54 +++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index d10ace729dc..031d53ce695 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -57,33 +57,33 @@ def _build_common_output(node, lib_name=None): + "**Library Type**: " + node["component"].get("libraryType", "") + "\n" - ) - lib_name = node["component"].get("name") - component_name = node["component"].get("artifactId") - component_version = node["component"].get("version") - 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") - mitigation = ( - "**Resolution**: " - + topfix_node.get("date", "") - + "\n" - + topfix_node.get("message", "") - + "\n" - + topfix_node.get("fixResolution", "") - + "\n" - ) - except Exception: - logger.exception("Error handling topFix node.") + ) + lib_name = node["component"].get("name") + component_name = node["component"].get("artifactId") + component_version = node["component"].get("version") + 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") + mitigation = ( + "**Resolution**: " + + topfix_node.get("date", "") + + "\n" + + topfix_node.get("message", "") + + "\n" + + topfix_node.get("fixResolution", "") + + "\n" + ) + except Exception: + logger.exception("Error handling topFix node.") elif "library" in node: node.get("project") description = ( From d4196e94418f3f7fc978d4fa1dcad8039c647c25 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:22:27 -0800 Subject: [PATCH 41/50] fix finding_info --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 031d53ce695..66ae30bfcb8 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -40,7 +40,7 @@ def _build_common_output(node, lib_name=None): cvss3_score = None mitigation = "N/A" locations = [] - if "component" in node and finding_info.get("status") == "ACTIVE": + if "component" in node and node.get("findingInfo", {}).get("status") == "ACTIVE": description = ( "**Vulnerability Description**: " + node["vulnerability"].get("description", "No Description Available") From 5ad78cb362133191b55c6ed1b3b45daf623c9673 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Sat, 21 Dec 2024 10:30:56 -0800 Subject: [PATCH 42/50] attempt to fix conditional logic for only getting ACTIVE findingInfo status --- dojo/tools/mend/parser.py | 89 ++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 66ae30bfcb8..e9c652145b6 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -40,50 +40,51 @@ def _build_common_output(node, lib_name=None): cvss3_score = None mitigation = "N/A" locations = [] - if "component" in node and node.get("findingInfo", {}).get("status") == "ACTIVE": - description = ( - "**Vulnerability Description**: " - + node["vulnerability"].get("description", "No Description Available") - + "\n\n" - + "**Component Name**: " - + node["component"].get("name", "") - + "\n" - + "**Component Type**: " - + node["component"].get("componentType", "") - + "\n" - + "**Root Library**: " - + str(node["component"].get("rootLibrary", "")) - + "\n" - + "**Library Type**: " - + node["component"].get("libraryType", "") - + "\n" - ) - lib_name = node["component"].get("name") - component_name = node["component"].get("artifactId") - component_version = node["component"].get("version") - 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") - mitigation = ( - "**Resolution**: " - + topfix_node.get("date", "") - + "\n" - + topfix_node.get("message", "") - + "\n" - + topfix_node.get("fixResolution", "") - + "\n" - ) - except Exception: - logger.exception("Error handling topFix node.") + if "component" in node: + if node.get("findingInfo", {}).get("status") == "ACTIVE": + description = ( + "**Vulnerability Description**: " + + node["vulnerability"].get("description", "No Description Available") + + "\n\n" + + "**Component Name**: " + + node["component"].get("name", "") + + "\n" + + "**Component Type**: " + + node["component"].get("componentType", "") + + "\n" + + "**Root Library**: " + + str(node["component"].get("rootLibrary", "")) + + "\n" + + "**Library Type**: " + + node["component"].get("libraryType", "") + + "\n" + ) + lib_name = node["component"].get("name") + component_name = node["component"].get("artifactId") + component_version = node["component"].get("version") + 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") + mitigation = ( + "**Resolution**: " + + topfix_node.get("date", "") + + "\n" + + topfix_node.get("message", "") + + "\n" + + topfix_node.get("fixResolution", "") + + "\n" + ) + except Exception: + logger.exception("Error handling topFix node.") elif "library" in node: node.get("project") description = ( From 1d0b7785a3beba206a58bf4742d67e8efe047488 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Sat, 21 Dec 2024 11:11:15 -0800 Subject: [PATCH 43/50] attempt to fix cve and title for new component logic --- dojo/tools/mend/parser.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index e9c652145b6..d39710e3cf0 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -69,6 +69,8 @@ def _build_common_output(node, lib_name=None): ) cvss3_score = node["vulnerability"].get("score", None) component_path = node["component"].get("path", None) + cve = node["vulnerability"].get("name") + title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name if component_path: locations.append(component_path) if "topFix" in node: @@ -108,6 +110,8 @@ def _build_common_output(node, lib_name=None): component_name = node["library"].get("artifactId") component_version = node["library"].get("version") cvss3_score = node.get("cvss3_score", None) + cve = node.get("name") + title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name if "topFix" in node: try: topfix_node = node.get("topFix") @@ -120,8 +124,8 @@ def _build_common_output(node, lib_name=None): else: description = node.get("description", "Unknown") - cve = node.get("name") - title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name + # cve = node.get("name") + # title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name # cvss2 by default in CLI, but cvss3 in UI. Adapting to have # homogeneous behavior. if "cvss3_severity" in node: From ed9a18cf6a0520aa7ebbe585ae39aff80dd1092e Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Sat, 21 Dec 2024 11:15:04 -0800 Subject: [PATCH 44/50] update unit test for new title check --- unittests/tools/test_mend_parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/tools/test_mend_parser.py b/unittests/tools/test_mend_parser.py index b68f51efc58..df875555a85 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -60,6 +60,7 @@ 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-multiple-findings.json", encoding="utf-8") as testfile: From 4c1e25c212e1c107e7070b416e10dd4cb35d6e08 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Sat, 21 Dec 2024 11:16:03 -0800 Subject: [PATCH 45/50] fix whitespace before comma --- 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 df875555a85..45a300e2e22 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -60,7 +60,7 @@ 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) + 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-multiple-findings.json", encoding="utf-8") as testfile: From 06704775edbbc703679882f1f01d91894d5003f6 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Sat, 21 Dec 2024 11:17:53 -0800 Subject: [PATCH 46/50] add unit test case for legacy title --- unittests/tools/test_mend_parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/tools/test_mend_parser.py b/unittests/tools/test_mend_parser.py index 45a300e2e22..75bbd54bcbb 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -43,6 +43,7 @@ def test_parse_file_with_one_sca_vuln_finding(self): self.assertEqual(1, len(findings)) finding = list(findings)[0] 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: From b7adf096df4838b6bb340bfa8fb5ddbf3581946e Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Sat, 21 Dec 2024 11:26:17 -0800 Subject: [PATCH 47/50] fix duplicate conditional - add into tree_node logic --- dojo/tools/mend/parser.py | 94 +++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index d39710e3cf0..ec7c7cdb9df 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -41,52 +41,51 @@ def _build_common_output(node, lib_name=None): mitigation = "N/A" locations = [] if "component" in node: - if node.get("findingInfo", {}).get("status") == "ACTIVE": - description = ( - "**Vulnerability Description**: " - + node["vulnerability"].get("description", "No Description Available") - + "\n\n" - + "**Component Name**: " - + node["component"].get("name", "") - + "\n" - + "**Component Type**: " - + node["component"].get("componentType", "") - + "\n" - + "**Root Library**: " - + str(node["component"].get("rootLibrary", "")) - + "\n" - + "**Library Type**: " - + node["component"].get("libraryType", "") - + "\n" - ) - lib_name = node["component"].get("name") - component_name = node["component"].get("artifactId") - component_version = node["component"].get("version") - impact = ( - "**Direct or Transitive Vulnerability**: " - + node["component"].get("dependencyType", "") - + "\n" - ) - cvss3_score = node["vulnerability"].get("score", None) - component_path = node["component"].get("path", None) - cve = node["vulnerability"].get("name") - title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name - if component_path: - locations.append(component_path) - if "topFix" in node: - try: - topfix_node = node.get("topFix") - mitigation = ( - "**Resolution**: " - + topfix_node.get("date", "") - + "\n" - + topfix_node.get("message", "") - + "\n" - + topfix_node.get("fixResolution", "") - + "\n" - ) - except Exception: - logger.exception("Error handling topFix node.") + description = ( + "**Vulnerability Description**: " + + node["vulnerability"].get("description", "No Description Available") + + "\n\n" + + "**Component Name**: " + + node["component"].get("name", "") + + "\n" + + "**Component Type**: " + + node["component"].get("componentType", "") + + "\n" + + "**Root Library**: " + + str(node["component"].get("rootLibrary", "")) + + "\n" + + "**Library Type**: " + + node["component"].get("libraryType", "") + + "\n" + ) + lib_name = node["component"].get("name") + component_name = node["component"].get("artifactId") + component_version = node["component"].get("version") + impact = ( + "**Direct or Transitive Vulnerability**: " + + node["component"].get("dependencyType", "") + + "\n" + ) + cvss3_score = node["vulnerability"].get("score", None) + component_path = node["component"].get("path", None) + cve = node["vulnerability"].get("name") + title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name + if component_path: + locations.append(component_path) + if "topFix" in node: + try: + topfix_node = node.get("topFix") + mitigation = ( + "**Resolution**: " + + topfix_node.get("date", "") + + "\n" + + topfix_node.get("message", "") + + "\n" + + topfix_node.get("fixResolution", "") + + "\n" + ) + except Exception: + logger.exception("Error handling topFix node.") elif "library" in node: node.get("project") description = ( @@ -255,7 +254,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.""" From 1c833af2ea56e55646a0ad4679a24af55f714c16 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Sat, 21 Dec 2024 11:39:38 -0800 Subject: [PATCH 48/50] add title logic back in --- dojo/tools/mend/parser.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index ec7c7cdb9df..cc18bf3175e 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -68,8 +68,6 @@ def _build_common_output(node, lib_name=None): ) cvss3_score = node["vulnerability"].get("score", None) component_path = node["component"].get("path", None) - cve = node["vulnerability"].get("name") - title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name if component_path: locations.append(component_path) if "topFix" in node: @@ -109,8 +107,6 @@ def _build_common_output(node, lib_name=None): component_name = node["library"].get("artifactId") component_version = node["library"].get("version") cvss3_score = node.get("cvss3_score", None) - cve = node.get("name") - title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name if "topFix" in node: try: topfix_node = node.get("topFix") @@ -123,8 +119,8 @@ def _build_common_output(node, lib_name=None): else: description = node.get("description", "Unknown") - # cve = node.get("name") - # title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name + cve = node.get("name") + title = "CVE-None | " + lib_name if cve is None else cve + " | " + lib_name # cvss2 by default in CLI, but cvss3 in UI. Adapting to have # homogeneous behavior. if "cvss3_severity" in node: From 32f79e14a59083a5e0c5c1d1f787e3a871ae8ad7 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 10 Jan 2025 10:07:47 -0800 Subject: [PATCH 49/50] add OPEN in addition to ACTIVE --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index cc18bf3175e..97869333507 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -250,7 +250,7 @@ def _build_common_output(node, lib_name=None): tree_node = content["response"] if tree_node: for node in tree_node: - if node.get("findingInfo", {}).get("status") == "ACTIVE": + if node.get("findingInfo", {}).get("status") == "ACTIVE" or "OPEN": findings.append(_build_common_output(node)) def create_finding_key(f: Finding) -> str: From 6b79958942f25e5eeec48f08598b775c44226e39 Mon Sep 17 00:00:00 2001 From: testaccount90009 <122134756+testaccount90009@users.noreply.github.com> Date: Fri, 10 Jan 2025 10:22:08 -0800 Subject: [PATCH 50/50] Update parser.py --- dojo/tools/mend/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 97869333507..cc18bf3175e 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -250,7 +250,7 @@ def _build_common_output(node, lib_name=None): tree_node = content["response"] if tree_node: for node in tree_node: - if node.get("findingInfo", {}).get("status") == "ACTIVE" or "OPEN": + if node.get("findingInfo", {}).get("status") == "ACTIVE": findings.append(_build_common_output(node)) def create_finding_key(f: Finding) -> str: