From 7a3ca4f9987899e81e1ea836881d7c375b987020 Mon Sep 17 00:00:00 2001 From: Marcos Carro Fernandez Date: Mon, 1 Sep 2025 12:25:06 +0200 Subject: [PATCH 1/8] Added nowsecure parser --- dojo/fixtures/test_type.json | 21 ++ dojo/tools/nowsecure/__init__.py | 0 dojo/tools/nowsecure/parser.py | 207 ++++++++++++++++++ .../scans/nowsecure/empty_with_error.json | 5 + .../scans/nowsecure/nowsecure_many_vul.json | 4 + .../scans/nowsecure/nowsecure_one_vul.json | 2 + .../scans/nowsecure/nowsecure_zero_vul.json | 2 + unittests/tools/test_nowsecure_parser.py | 49 +++++ 8 files changed, 290 insertions(+) create mode 100644 dojo/tools/nowsecure/__init__.py create mode 100644 dojo/tools/nowsecure/parser.py create mode 100644 unittests/scans/nowsecure/empty_with_error.json create mode 100644 unittests/scans/nowsecure/nowsecure_many_vul.json create mode 100644 unittests/scans/nowsecure/nowsecure_one_vul.json create mode 100644 unittests/scans/nowsecure/nowsecure_zero_vul.json create mode 100644 unittests/tools/test_nowsecure_parser.py diff --git a/dojo/fixtures/test_type.json b/dojo/fixtures/test_type.json index d1a9fa60726..9eb294411d1 100644 --- a/dojo/fixtures/test_type.json +++ b/dojo/fixtures/test_type.json @@ -47,5 +47,26 @@ }, "model": "dojo.test_type", "pk": 7 + }, + { + "fields": { + "name": "NowSecure" + }, + "model": "dojo.test_type", + "pk": 8 + }, + { + "fields": { + "name": "NowSecure" + }, + "model": "dojo.test_type", + "pk": 9 + }, + { + "fields": { + "name": "NowSecure" + }, + "model": "dojo.test_type", + "pk": 10 } ] \ No newline at end of file diff --git a/dojo/tools/nowsecure/__init__.py b/dojo/tools/nowsecure/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dojo/tools/nowsecure/parser.py b/dojo/tools/nowsecure/parser.py new file mode 100644 index 00000000000..e4b5c6f282e --- /dev/null +++ b/dojo/tools/nowsecure/parser.py @@ -0,0 +1,207 @@ +# import hashlib +# import json +# from urllib.parse import urlparse +# from dojo.models import Endpoint, Finding + + +# class NowSecureParser(object): +# """ +# testing apps that touch your enterprise, preventing data leakage or unauthorized access. +# """ + +# def get_scan_types(self): +# return ["NowSecure Scan"] + +# def get_label_for_scan_types(self, scan_type): +# return "NowSecure Scan" + +# def get_description_for_scan_types(self, scan_type): +# return "NowSecure report file can be imported in JSON format (option --json)." + +# def get_findings(self, file, test): +# data = json.load(file) + +# dupes = dict() +# for content in tree: +# node = tree[content] +# if not node['pass']: +# title = node['name'] +# description = "**Score Description** : " + node['score_description'] + "\n\n" + \ +# "**Result** : " + node['result'] + "\n\n" + \ +# "**expectation** : " + node['expectation'] + "\n" +# severity = self.get_severity(int(node['score_modifier'])) +# output = node['output'] +# try: +# url = output['destination'] +# parsedUrl = urlparse(url) +# protocol = parsedUrl.scheme +# query = parsedUrl.query +# fragment = parsedUrl.fragment +# path = parsedUrl.path +# port = "" +# try: +# host, port = parsedUrl.netloc.split(':') +# except: +# host = parsedUrl.netloc +# except: +# url = None + +# finding = Finding( +# title=title, +# test=test, +# description=description, +# severity=severity, + +# static_finding=True, +# dynamic_finding=False, +# ) + +# # some attribute are optional +# if 'mitigationFromTheTool' in node: +# finding.mitigation = node['mitigationFromTheTool'] + +# # take a look at all the attributes possible in the documentation +# # some are very usefull like +# # - date (DATE / date when the finding was detected) +# # - component_name (STRING / if the finding is liked to an external component ex: 'log4j') +# # - component_version (STRING / if the finding is liked to an external component ex: '1.2.13') +# # - file_path (STRING / if the finding is liked to a specfic file ex: 'src/foo.c') +# # - line (INTEGER / if the finding is liked to an specific file ex: 23) + +# # manage endpoint +# finding.unsaved_endpoints = list() +# if url is not None: +# finding.unsaved_endpoints.append(Endpoint( +# host=host, port=port, +# path=path, +# protocol=protocol, +# query=query, fragment=fragment)) + +# # internal de-duplication +# dupe_key = hashlib.sha256(str(description + title).encode('utf-8')).hexdigest() +# if dupe_key in dupes: +# find = dupes[dupe_key] +# if finding.description: +# find.description += "\n" + finding.description +# find.unsaved_endpoints.extend(finding.unsaved_endpoints) +# dupes[dupe_key] = find +# else: +# dupes[dupe_key] = finding + +# return list(dupes.values()) + +# def convert_severity(self, num_severity): +# """Convert severity value""" +# if num_severity >= -10: +# return "Low" +# elif -11 >= num_severity > -26: +# return "Medium" +# elif num_severity <= -26: +# return "High" +# else: +# return "Info" +import hashlib +import json +from urllib.parse import urlparse +from dojo.models import Endpoint, Finding +import re + +class NowSecureParser(object): + """ + Importing findings from NowSecure app analysis. + """ + + def get_scan_types(self): + return ["NowSecure Scan"] + + def get_label_for_scan_types(self, scan_type): + return "NowSecure Scan" + + def get_description_for_scan_types(self, scan_type): + return "NowSecure report file can be imported in JSON format (option --json)." + + def get_findings(self, file, test): + data = json.load(file) + + dupes = dict() + for content in data['data']['auto']['assessment']['report']['findings']: + if content['affected']: + if content['check']['issue']: + title = content['check']['issue']['title'] + for regulation in content['check']['issue']['regulations']: + if regulation['type'] == "cwe": + cwe = regulation['links'][0]['title'] + description = content['check']['issue']['description'] + severity = content['check']['issue']['severity'].capitalize() + cvssv3 = content['check']['issue']['cvssVector'] + cvssv3_score = content['check']['issue']['cvss'] + mitigation = content['check']['issue']['recommendation'] + impact = content['check']['issue']['impactSummary'] + url = f"https://app.nowsecure.com/app/{data['data']['auto']['assessment']['applicationRef']}/assessment/{data['data']['auto']['assessment']['ref']}?viewObservationsBy=categories&viewFindingsBy=policyCategory#{content['checkId']}" + steps_to_reproduce = (content['check']['issue']['stepsToReproduce'] or '''''') + if content['check']['issue']['codeSamples']: + code_samples = '''''' + for code_sample in content['check']['issue']['codeSamples']: + code_samples += f'''**{code_sample['platform']}**: {code_sample['caption']}\n```{code_sample['syntax']}\n{code_sample['block']}\n```\n''' + if code_samples: + steps_to_reproduce += code_samples + references = '''''' + if content['check']['issue']['guidanceLinks']: + references+="### Guidance Links\n" + for reference in content['check']['issue']['guidanceLinks']: + references+=f'''* [{reference['caption']}]({reference['url']})\n''' + + cwe = None + if content['check']['issue']['regulations']: + references+="### Regulations\n" + for regulation in content['check']['issue']['regulations']: + if regulation['type'] == 'cwe': + cwe = regulation['links'][0]['title'] + for link in regulation['links']: + references+=f"* **{regulation['label']}**: [{link['title']}]({link['url']})\n" + cve = None + cve_pattern = r'CVE-\d{4}-\d{4,7}' + cve_matches = re.findall(cve_pattern, title) + if cve_matches: + cve = list(dict.fromkeys(cve_matches))[0] + + finding = Finding( + title=title, + test=test, + description=description, + severity=severity, + cvssv3 = cvssv3, + cvssv3_score = cvssv3_score, + mitigation = mitigation, + url = url, + steps_to_reproduce = steps_to_reproduce, + impact=impact, + references = references, + cwe = cwe, + cve = cve, + + static_finding=True, + dynamic_finding=False, +) + dupe_key = hashlib.sha256(str(description + title).encode('utf-8')).hexdigest() + if dupe_key in dupes: + find = dupes[dupe_key] + if finding.description: + find.description += "\n" + finding.description + find.unsaved_endpoints.extend(finding.unsaved_endpoints) + dupes[dupe_key] = find + else: + dupes[dupe_key] = finding + + return list(dupes.values()) + + def convert_severity(self, num_severity): + """Convert severity value""" + if num_severity >= -10: + return "Low" + elif -11 >= num_severity > -26: + return "Medium" + elif num_severity <= -26: + return "High" + else: + return "Info" \ No newline at end of file diff --git a/unittests/scans/nowsecure/empty_with_error.json b/unittests/scans/nowsecure/empty_with_error.json new file mode 100644 index 00000000000..6617e9b45ea --- /dev/null +++ b/unittests/scans/nowsecure/empty_with_error.json @@ -0,0 +1,5 @@ +{"type":"warning","data":"package.json: No license field"} +{"type":"warning","data":"No license field"} +{"type":"error","data":"An unexpected error occurred: \"https://registry.yarnpkg.com/-/npm/v1/security/audits: tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:80\"."} +{"type":"info","data":"If you think this is a bug, please open a bug report with the information provided in \"/yarn-error.log\"."} +{"type":"info","data":"Visit https://yarnpkg.com/en/docs/cli/audit for documentation about this command."} diff --git a/unittests/scans/nowsecure/nowsecure_many_vul.json b/unittests/scans/nowsecure/nowsecure_many_vul.json new file mode 100644 index 00000000000..7e5a223abd6 --- /dev/null +++ b/unittests/scans/nowsecure/nowsecure_many_vul.json @@ -0,0 +1,4 @@ +{"type":"auditAdvisory","data":{"resolution":{"id":1179,"path":"handlebars>optimist>minimist","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"0.0.10","paths":["handlebars>optimist>minimist"]}],"id":1179,"created":"2019-09-23T15:01:43.049Z","updated":"2020-03-18T19:41:45.921Z","deleted":null,"title":"Prototype Pollution","found_by":{"link":"https://www.checkmarx.com/resources/blog/","name":"Checkmarx Research Team","email":""},"reported_by":{"link":"https://www.checkmarx.com/resources/blog/","name":"Checkmarx Research Team","email":""},"module_name":"minimist","cves":[],"vulnerable_versions":"<0.2.1 || >=1.0.0 <1.2.3","patched_versions":">=0.2.1 <1.0.0 || >=1.2.3","overview":"Affected versions of `minimist` are vulnerable to prototype pollution. Arguments are not properly sanitized, allowing an attacker to modify the prototype of `Object`, causing the addition or modification of an existing property that will exist on all objects. \nParsing the argument `--__proto__.y=Polluted` adds a `y` property with value `Polluted` to all objects. The argument `--__proto__=Polluted` raises and uncaught error and crashes the application. \nThis is exploitable if attackers have control over the arguments being passed to `minimist`.\n","recommendation":"Upgrade to versions 0.2.1, 1.2.3 or later.","references":"- [GitHub commit 1](https://github.com/substack/minimist/commit/4cf1354839cb972e38496d35e12f806eea92c11f#diff-a1e0ee62c91705696ddb71aa30ad4f95)\n- [GitHub commit 2](https://github.com/substack/minimist/commit/63e7ed05aa4b1889ec2f3b196426db4500cbda94)","access":"public","severity":"low","cwe":"CWE-471","metadata":{"module_type":"","exploitability":1,"affected_components":""},"url":"https://npmjs.com/advisories/1179"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1324,"path":"handlebars","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.5.2","paths":["handlebars"]}],"id":1324,"created":"2019-11-18T19:06:46.461Z","updated":"2020-02-26T17:51:49.573Z","deleted":null,"title":"Arbitrary Code Execution","found_by":{"link":"","name":"Unknown","email":""},"reported_by":{"link":"","name":"Unknown","email":""},"module_name":"handlebars","cves":[],"vulnerable_versions":"<3.0.8 || >=4.0.0 <4.5.3","patched_versions":">=3.0.8 <4.0.0 || >=4.5.3","overview":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It is due to an incomplete fix for a [previous issue](https://www.npmjs.com/advisories/1316). This vulnerability can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).","recommendation":"Upgrade to version 3.0.8, 4.5.3 or later.","references":"","access":"public","severity":"high","cwe":"CWE-79","metadata":{"module_type":"","exploitability":4,"affected_components":""},"url":"https://npmjs.com/advisories/1324"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1325,"path":"handlebars","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.5.2","paths":["handlebars"]}],"id":1325,"created":"2019-11-18T19:42:01.445Z","updated":"2020-02-26T17:55:51.120Z","deleted":null,"title":"Prototype Pollution","found_by":{"link":"","name":"Vladyslav Babkin","email":""},"reported_by":{"link":"","name":"Vladyslav Babkin","email":""},"module_name":"handlebars","cves":[],"vulnerable_versions":"<3.0.8 || >=4.0.0 <4.5.3","patched_versions":">=3.0.8 <4.0.0 || >=4.5.3","overview":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to prototype pollution. It is possible to add or modify properties to the Object prototype through a malicious template. This may allow attackers to crash the application or execute Arbitrary Code in specific conditions.","recommendation":"Upgrade to version 3.0.8, 4.5.3 or later.","references":"","access":"public","severity":"high","cwe":"CWE-471","metadata":{"module_type":"","exploitability":4,"affected_components":""},"url":"https://npmjs.com/advisories/1325"}}} +{"type":"auditSummary","data":{"vulnerabilities":{"info":0,"low":1,"moderate":0,"high":2,"critical":0},"dependencies":47,"devDependencies":0,"optionalDependencies":0,"totalDependencies":47}} diff --git a/unittests/scans/nowsecure/nowsecure_one_vul.json b/unittests/scans/nowsecure/nowsecure_one_vul.json new file mode 100644 index 00000000000..da8bda60f9d --- /dev/null +++ b/unittests/scans/nowsecure/nowsecure_one_vul.json @@ -0,0 +1,2 @@ +{"type":"auditAdvisory","data":{"resolution":{"id":1325,"path":"handlebars","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.5.2","paths":["handlebars"]}],"id":1325,"created":"2019-11-18T19:42:01.445Z","updated":"2020-02-26T17:55:51.120Z","deleted":null,"title":"Prototype Pollution","found_by":{"link":"","name":"Vladyslav Babkin","email":""},"reported_by":{"link":"","name":"Vladyslav Babkin","email":""},"module_name":"handlebars","cves":[],"vulnerable_versions":"<3.0.8 || >=4.0.0 <4.5.3","patched_versions":">=3.0.8 <4.0.0 || >=4.5.3","overview":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to prototype pollution. It is possible to add or modify properties to the Object prototype through a malicious template. This may allow attackers to crash the application or execute Arbitrary Code in specific conditions.","recommendation":"Upgrade to version 3.0.8, 4.5.3 or later.","references":"","access":"public","severity":"high","cwe":"CWE-471","metadata":{"module_type":"","exploitability":4,"affected_components":""},"url":"https://npmjs.com/advisories/1325"}}} +{"type":"auditSummary","data":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":1,"critical":0},"dependencies":47,"devDependencies":0,"optionalDependencies":0,"totalDependencies":47}} diff --git a/unittests/scans/nowsecure/nowsecure_zero_vul.json b/unittests/scans/nowsecure/nowsecure_zero_vul.json new file mode 100644 index 00000000000..38f53ef6e42 --- /dev/null +++ b/unittests/scans/nowsecure/nowsecure_zero_vul.json @@ -0,0 +1,2 @@ +{"type":"info","data":"No lockfile found."} +{"type":"auditSummary","data":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":0,"critical":0},"dependencies":0,"devDependencies":0,"optionalDependencies":0,"totalDependencies":0}} diff --git a/unittests/tools/test_nowsecure_parser.py b/unittests/tools/test_nowsecure_parser.py new file mode 100644 index 00000000000..17aaa2a5b69 --- /dev/null +++ b/unittests/tools/test_nowsecure_parser.py @@ -0,0 +1,49 @@ +from django.test import TestCase +from dojo.tools.nowsecure.parser import NowSecureParser +from dojo.models import Test + + +class TestNowSecureParser(TestCase): + + def test_nowsecure_parser_with_no_vuln_has_no_findings(self): + testfile = open("unittests/scans/nowsecure/nowsecure_zero_vul.json") + parser = NowSecureParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + self.assertEqual(0, len(findings)) + + def test_nowsecure_parser_with_one_criticle_vuln_has_one_findings(self): + testfile = open("unittests/scans/nowsecure/nowsecure_one_vul.json") + parser = NowSecureParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + self.assertEqual("handlebars", findings[0].component_name) + self.assertEqual("4.5.2", findings[0].component_version) + + def test_nowsecure_parser_with_many_vuln_has_many_findings(self): + testfile = open("unittests/scans/nowsecure/nowsecure_many_vul.json") + parser = NowSecureParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(3, len(findings)) + + def test_nowsecure_parser_empty_with_error(self): + with self.assertRaises(ValueError) as context: + testfile = open("unittests/scans/nowsecure/empty_with_error.json") + parser = NowSecureParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertTrue( + "NowSecure report contains errors:" in str(context.exception) + ) + self.assertTrue("ECONNREFUSED" in str(context.exception)) From 792c0bdec0ca5177ab76156320b65b67537cb7d4 Mon Sep 17 00:00:00 2001 From: Marcos Carro Fernandez Date: Mon, 1 Sep 2025 14:40:44 +0200 Subject: [PATCH 2/8] Added nowsecure unittests --- .../scans/nowsecure/empty_with_error.json | 5 - .../scans/nowsecure/nowsecure_many_vul.json | 4 - .../scans/nowsecure/nowsecure_many_vuln.json | 2860 +++++++++++++++++ .../scans/nowsecure/nowsecure_one_vul.json | 2 - .../scans/nowsecure/nowsecure_one_vuln.json | 2073 ++++++++++++ .../scans/nowsecure/nowsecure_zero_vul.json | 2 - .../scans/nowsecure/nowsecure_zero_vuln.json | 1758 ++++++++++ unittests/tools/test_nowsecure_parser.py | 55 +- 8 files changed, 6726 insertions(+), 33 deletions(-) delete mode 100644 unittests/scans/nowsecure/empty_with_error.json delete mode 100644 unittests/scans/nowsecure/nowsecure_many_vul.json create mode 100644 unittests/scans/nowsecure/nowsecure_many_vuln.json delete mode 100644 unittests/scans/nowsecure/nowsecure_one_vul.json create mode 100644 unittests/scans/nowsecure/nowsecure_one_vuln.json delete mode 100644 unittests/scans/nowsecure/nowsecure_zero_vul.json create mode 100644 unittests/scans/nowsecure/nowsecure_zero_vuln.json diff --git a/unittests/scans/nowsecure/empty_with_error.json b/unittests/scans/nowsecure/empty_with_error.json deleted file mode 100644 index 6617e9b45ea..00000000000 --- a/unittests/scans/nowsecure/empty_with_error.json +++ /dev/null @@ -1,5 +0,0 @@ -{"type":"warning","data":"package.json: No license field"} -{"type":"warning","data":"No license field"} -{"type":"error","data":"An unexpected error occurred: \"https://registry.yarnpkg.com/-/npm/v1/security/audits: tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:80\"."} -{"type":"info","data":"If you think this is a bug, please open a bug report with the information provided in \"/yarn-error.log\"."} -{"type":"info","data":"Visit https://yarnpkg.com/en/docs/cli/audit for documentation about this command."} diff --git a/unittests/scans/nowsecure/nowsecure_many_vul.json b/unittests/scans/nowsecure/nowsecure_many_vul.json deleted file mode 100644 index 7e5a223abd6..00000000000 --- a/unittests/scans/nowsecure/nowsecure_many_vul.json +++ /dev/null @@ -1,4 +0,0 @@ -{"type":"auditAdvisory","data":{"resolution":{"id":1179,"path":"handlebars>optimist>minimist","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"0.0.10","paths":["handlebars>optimist>minimist"]}],"id":1179,"created":"2019-09-23T15:01:43.049Z","updated":"2020-03-18T19:41:45.921Z","deleted":null,"title":"Prototype Pollution","found_by":{"link":"https://www.checkmarx.com/resources/blog/","name":"Checkmarx Research Team","email":""},"reported_by":{"link":"https://www.checkmarx.com/resources/blog/","name":"Checkmarx Research Team","email":""},"module_name":"minimist","cves":[],"vulnerable_versions":"<0.2.1 || >=1.0.0 <1.2.3","patched_versions":">=0.2.1 <1.0.0 || >=1.2.3","overview":"Affected versions of `minimist` are vulnerable to prototype pollution. Arguments are not properly sanitized, allowing an attacker to modify the prototype of `Object`, causing the addition or modification of an existing property that will exist on all objects. \nParsing the argument `--__proto__.y=Polluted` adds a `y` property with value `Polluted` to all objects. The argument `--__proto__=Polluted` raises and uncaught error and crashes the application. \nThis is exploitable if attackers have control over the arguments being passed to `minimist`.\n","recommendation":"Upgrade to versions 0.2.1, 1.2.3 or later.","references":"- [GitHub commit 1](https://github.com/substack/minimist/commit/4cf1354839cb972e38496d35e12f806eea92c11f#diff-a1e0ee62c91705696ddb71aa30ad4f95)\n- [GitHub commit 2](https://github.com/substack/minimist/commit/63e7ed05aa4b1889ec2f3b196426db4500cbda94)","access":"public","severity":"low","cwe":"CWE-471","metadata":{"module_type":"","exploitability":1,"affected_components":""},"url":"https://npmjs.com/advisories/1179"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1324,"path":"handlebars","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.5.2","paths":["handlebars"]}],"id":1324,"created":"2019-11-18T19:06:46.461Z","updated":"2020-02-26T17:51:49.573Z","deleted":null,"title":"Arbitrary Code Execution","found_by":{"link":"","name":"Unknown","email":""},"reported_by":{"link":"","name":"Unknown","email":""},"module_name":"handlebars","cves":[],"vulnerable_versions":"<3.0.8 || >=4.0.0 <4.5.3","patched_versions":">=3.0.8 <4.0.0 || >=4.5.3","overview":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It is due to an incomplete fix for a [previous issue](https://www.npmjs.com/advisories/1316). This vulnerability can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).","recommendation":"Upgrade to version 3.0.8, 4.5.3 or later.","references":"","access":"public","severity":"high","cwe":"CWE-79","metadata":{"module_type":"","exploitability":4,"affected_components":""},"url":"https://npmjs.com/advisories/1324"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1325,"path":"handlebars","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.5.2","paths":["handlebars"]}],"id":1325,"created":"2019-11-18T19:42:01.445Z","updated":"2020-02-26T17:55:51.120Z","deleted":null,"title":"Prototype Pollution","found_by":{"link":"","name":"Vladyslav Babkin","email":""},"reported_by":{"link":"","name":"Vladyslav Babkin","email":""},"module_name":"handlebars","cves":[],"vulnerable_versions":"<3.0.8 || >=4.0.0 <4.5.3","patched_versions":">=3.0.8 <4.0.0 || >=4.5.3","overview":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to prototype pollution. It is possible to add or modify properties to the Object prototype through a malicious template. This may allow attackers to crash the application or execute Arbitrary Code in specific conditions.","recommendation":"Upgrade to version 3.0.8, 4.5.3 or later.","references":"","access":"public","severity":"high","cwe":"CWE-471","metadata":{"module_type":"","exploitability":4,"affected_components":""},"url":"https://npmjs.com/advisories/1325"}}} -{"type":"auditSummary","data":{"vulnerabilities":{"info":0,"low":1,"moderate":0,"high":2,"critical":0},"dependencies":47,"devDependencies":0,"optionalDependencies":0,"totalDependencies":47}} diff --git a/unittests/scans/nowsecure/nowsecure_many_vuln.json b/unittests/scans/nowsecure/nowsecure_many_vuln.json new file mode 100644 index 00000000000..35dc9163d78 --- /dev/null +++ b/unittests/scans/nowsecure/nowsecure_many_vuln.json @@ -0,0 +1,2860 @@ +{ + "data": { + "auto": { + "assessment": { + "ref": "13371337-1337-1337-1337-133713371337", + "applicationRef": "73317331-7331-7331-7331-733173317331", + "platformType": "android", + "packageKey": "com.org.appname", + "packageVersion": "1.0.0", + "taskId": "1231231231231", + "title": "AppName", + "iconURL": "https://api.nowsecure.com/icon/hjfkjz9mxb3bxy3zi1ohraj60oqtpbw63wnvgon8l1ytt49dqwickoczrzopvkvb", + "isAppstoreDownload": false, + "createdAt": "2025-06-20T06:47:15.551Z", + "createdBy": { + "ref": "123123aa-129a-1223-ba11-129c91234asf", + "email": "user@email.com", + "name": "John Doe", + "__typename": "UserSummary" + }, + "buildRef": "123123aa-123a-1a31-123a-1231aa112311", + "buildVersion": "010000", + "upload": { + "ref": "1231acc1-123a-129f-19af-0aa123018391", + "createdAt": "2025-06-20T06:45:16.788Z", + "digest": "25tnhu7gc0u70lw9jnc120rilyz2z1blfnhssinqsgnvpjtvafj0x82ddfclyzri", + "__typename": "AutoUpload" + }, + "analysisConfigLevel": "BASELINE", + "type": "baseline", + "analysisJobType": "FULL", + "staticScore": null, + "score": 86.5, + "favorite": false, + "assessmentError": null, + "isDebugMode": false, + "hasPreviousAssessmentForComparison": false, + "policy": { + "ref": "1a11aa11-1111-1111-a111-11111aaa1111", + "name": "NowSecure Default Policy", + "createdBy": null, + "createdAt": "2022-07-06T11:04:26.575Z", + "updatedAt": "2025-08-20T16:25:34.128Z", + "archivedAt": null, + "targetType": "ORGANIZATION", + "isDefault": true, + "isNSManaged": true, + "latestVersion": { + "ref": "1111a11a-11aa-1aa1-1a1a-111a11111aa1", + "version": 60, + "trackedVersion": null, + "trackedVersionRef": null, + "__typename": "PolicyVersion" + }, + "targets": [ + { + "ref": "a1a111aa-111a-11aa-111a-11a111a1a1a1", + "type": "ORGANIZATION", + "__typename": "PolicyTarget" + } + ], + "enabled": true, + "trackedPolicy": null, + "__typename": "Policy" + }, + "policyVersion": { + "ref": "a11aa111-1a11-1111-1a1a-11aaa1a111a1", + "policyRef": "1a11aa11-1111-1111-a111-11111aaa1111", + "version": 56, + "policyCategories": [ + { + "policyCategory": 1, + "label": "Needs Remediation", + "description": "NowSecure suggests remediation", + "color": "#CA1108", + "__typename": "PolicyCategory" + }, + { + "policyCategory": 2, + "label": "Review Required", + "description": "NowSecure suggests security review to determine risk", + "color": "#FBA255", + "__typename": "PolicyCategory" + }, + { + "policyCategory": 3, + "label": "Informational", + "description": "NowSecure suggests general review for audit and information", + "color": "#0099ff", + "__typename": "PolicyCategory" + } + ], + "__typename": "PolicyVersion" + }, + "analysis": { + "isAuthenticated": null, + "isCancelled": false, + "isComplete": true, + "isRunning": false, + "status": "completed", + "mappedStatus": "completed", + "errorCode": null, + "error": null, + "artifacts": [ + { + "assessmentRef": "13371337-1337-1337-1337-133713371337", + "ref": "111111a1-1111-11aa-a11a-a111aa111a11", + "artifactType": "HAR", + "tags": "dynamic combined har", + "displayName": "Download artifact for Combined HAR", + "byteSize": 243826, + "filename": "combined.har", + "contentType": "application/json", + "url": "/v4/asset/artifact/13371337-1337-1337-1337-133713371337/111111a1-1111-11aa-a11a-a111aa111a11", + "__typename": "AnalysisArtifact" + }, + { + "assessmentRef": "13371337-1337-1337-1337-133713371337", + "ref": "aa111a1a-a1aa-11a1-1a11-a1aa1111aaaa", + "artifactType": "HAR", + "tags": "dynamic combined har", + "displayName": "Download artifact for Combined HAR+Beat", + "byteSize": 446396, + "filename": "combined_with_beat.har", + "contentType": "application/json", + "url": "/v4/asset/artifact/13371337-1337-1337-1337-133713371337/aa111a1a-a1aa-11a1-1a11-a1aa1111aaaa", + "__typename": "AnalysisArtifact" + } + ], + "screenshots": [ + { + "ref": "111111a1-a111-111a-11aa-1aa11111a1a1", + "url": "/v4/asset/screenshot/13371337-1337-1337-1337-133713371337/111111a1-a111-111a-11aa-1aa11111a1a1", + "analysisPass": 1, + "__typename": "AnalysisScreenshot" + }, + { + "ref": "1111a111-aaaa-1a1a-1a1a-a111a1a1a11a", + "url": "/v4/asset/screenshot/13371337-1337-1337-1337-133713371337/1111a111-aaaa-1a1a-1a1a-a111a1a1a11a", + "analysisPass": 1, + "__typename": "AnalysisScreenshot" + } + ], + "task": { + "static": { + "id": "1231231231231.static", + "status": "completed", + "modifiedAt": "2025-06-20T07:18:45.377Z", + "isRunning": false, + "isComplete": true, + "__typename": "AnalysisJob" + }, + "dynamic": { + "id": "1231231231231.dynamic", + "status": "completed", + "modifiedAt": "2025-06-20T07:18:36.233Z", + "isRunning": false, + "isComplete": true, + "__typename": "AnalysisJob" + }, + "__typename": "AnalysisTask" + }, + "__typename": "AutoAssessmentAnalysis" + }, + "build": { + "ref": "123123aa-123a-1a31-123a-1231aa112311", + "digest": "25tnhu7gc0u70lw9jnc120rilyz2z1blfnhssinqsgnvpjtvafj0x82ddfclyzri", + "version": "1.0.0", + "__typename": "AutoBuild" + }, + "group": { + "ref": "a111aaaa-aa11-11aa-1a11-11a111aa1111", + "__typename": "AutoGroup" + }, + "__typename": "AutoAssessment", + "report": { + "createdAt": "2025-06-20T06:47:15.551Z", + "findings": [ + { + "affected": true, + "checkId": "apk_insecure_network_config", + "uniqueVulnerabilityId": 2802557, + "check": { + "id": "apk_insecure_network_config", + "analysisType": "static", + "title": "App Configuration Allows Insecure Network Connections", + "description": "This check analyzes the app and looks for settings that allow cleartext traffic, such as `android:usesCleartextTraffic` in the `AndroidManifest.xml` file and `cleartextTrafficPermitted` in the Network Security Config file.", + "shortDescription": "Allowing insecure connections increases the risk of exposing sensitive data. Applications should explicitly disable cleartext communications, in order to avoid data interception or modification, which compromises sensitive information.", + "platformType": "android", + "category": "network", + "categories": [ + "Networking" + ], + "legacyFindingKey": "apk_insecure_network_config", + "isNew": false, + "deprecated": false, + "context": { + "view": "table", + "title": "Network Configurations Allowing Cleartext Traffic", + "fields": [ + { + "key": "source", + "format": null, + "title": "Source", + "description": "the file type that allows insecure access", + "__typename": "FindingContextField" + }, + { + "key": "xml_element", + "format": null, + "title": "XML Element", + "description": "the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)", + "__typename": "FindingContextField" + }, + { + "key": "xml_attribute", + "format": null, + "title": "XML Attribute", + "description": "the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)", + "__typename": "FindingContextField" + }, + { + "key": "default_used", + "format": null, + "title": "Uses SDK Default", + "description": "states if the Android SDK version's default value was used", + "__typename": "FindingContextField" + }, + { + "key": "allow_cleartext", + "format": null, + "title": "Allow Cleartext", + "description": "value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed", + "__typename": "FindingContextField" + }, + { + "key": "domain", + "format": null, + "title": "Domain", + "description": "the domain that allows cleartext data (only present if is used)", + "__typename": "FindingContextField" + }, + { + "key": "include_subdomains", + "format": null, + "title": "Includes Subdomains", + "description": "value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)", + "__typename": "FindingContextField" + } + ], + "children": null, + "__typename": "FindingContextMetadata" + }, + "issue": { + "cvss": 7.5, + "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", + "title": "App Configuration Allows Insecure Network Connections", + "description": "The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.", + "recommendation": "The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).", + "passingContent": "The app has no insecure settings allowing cleartext connections.", + "category": "network", + "severity": "high", + "warn": false, + "impactSummary": "Allowing cleartext network connections allows attackers to intercept, inspect or manipulate data transmitted between the app and external servers, compromising the integrity and confidentiality of user information. This vulnerability can have serious business implications, particularly in the event of a data breach, including loss of customer trust, potential legal liabilities and financial penalties.", + "regulations": [ + { + "type": "cwe", + "label": "CWE", + "links": [ + { + "title": "319", + "url": "https://cwe.mitre.org/data/definitions/319.html", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "fisma_low", + "label": "FISMA LOW", + "links": [ + { + "title": "SC-13 CRYPTOGRAPHIC PROTECTION", + "url": "https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=SC-13", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "fisma_med", + "label": "FISMA MED", + "links": [ + { + "title": "SC-8 TRANSMISSION CONFIDENTIALITY AND INTEGRITY", + "url": "https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=SC-8", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "owasp", + "label": "Risk OWASP", + "links": [ + { + "title": "MSTG-NETWORK-1 (OWASP MASVS v1.5.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v1.5.0/Document/0x10-V5-Network_communication_requirements.md", + "__typename": "RegulatoryLink" + }, + { + "title": "MASVS-NETWORK-1 (OWASP MASVS v2.1.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v2.1.0/controls/MASVS-NETWORK-1.md", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "gdpr", + "label": "GDPR", + "links": [ + { + "title": "Risks violating Article 25", + "url": "https://gdpr-info.eu/art-25-gdpr/", + "__typename": "RegulatoryLink" + }, + { + "title": "Risks violating Article 32", + "url": "https://gdpr-info.eu/art-32-gdpr/", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "ffiec", + "label": "FFIEC", + "links": [ + { + "title": "May violate D3.PC.Am.Int.7", + "url": "https://www.ffiec.gov/pdf/cybersecurity/FFIEC_CAT_May_2017.pdf", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "pci", + "label": "PCI", + "links": [ + { + "title": "May violate requirement 4.1", + "url": "https://www.pcisecuritystandards.org/document_library?document=pci_dss", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "hipaa", + "label": "HIPAA", + "links": [ + { + "title": "May violate ยง164.312(e)(1): Standard: Transmission security.", + "url": "https://www.hhs.gov/sites/default/files/ocr/privacy/hipaa/administrative/securityrule/techsafeguards.pdf?language=es", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "ccpa", + "label": "CCPA", + "links": [ + { + "title": "Risks violating CCPA: exfiltration, theft, or disclosure of PII", + "url": "https://cdp.cooley.com/ccpa-2018/#section-1798-150", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + } + ], + "stepsToReproduce": null, + "codeSamples": [ + { + "platform": "android", + "syntax": "xml", + "caption": "Good Code Example", + "block": "\n\n \n\n", + "__typename": "IssueCodeSample" + } + ], + "guidanceLinks": [ + { + "platform": "android", + "caption": "Android Developer Documentation - Android Manifest", + "url": "https://developer.android.com/guide/topics/manifest/manifest-intro", + "__typename": "IssueGuidanceLink" + }, + { + "platform": "android", + "caption": "Android Developer Documentation - `usesCleartextTraffic` field", + "url": "https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic", + "__typename": "IssueGuidanceLink" + }, + { + "platform": "android", + "caption": "Android Developer Documentation - Network Security Config", + "url": "https://developer.android.com/privacy-and-security/security-config", + "__typename": "IssueGuidanceLink" + } + ], + "__typename": "FindingIssue" + }, + "compliance": null, + "__typename": "FindingCheck" + }, + "userChanges": null, + "cvss": 7.5, + "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", + "findingStatus": "detected", + "decision": "NONE", + "decisionInfo": null, + "evidenceDecision": "NONE", + "hidden": false, + "impactType": "high", + "severity": "high", + "note": null, + "adjustments": [], + "shortRemediation": null, + "title": "App Configuration Allows Insecure Network Connections", + "hasContext": true, + "hasCodeLocations": false, + "canHaveActionableEvidence": true, + "hasActionedEvidence": false, + "policyCategory": { + "policyCategory": 1, + "color": "#CA1108", + "label": "Needs Remediation", + "__typename": "PolicyCategory" + }, + "policyFindingOverrides": { + "checkId": "apk_insecure_network_config", + "cvss": 7.5, + "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", + "hidden": false, + "impactType": "high", + "__typename": "PolicyFinding" + }, + "complianceReportRelations": [ + { + "catalog": "MASVS", + "groupId": "MASVS-NETWORK", + "controlId": "MSTG-NETWORK-1", + "version": "1", + "__typename": "ComplianceReportRelation" + }, + { + "catalog": "MASVS", + "groupId": "MASVS-NETWORK", + "controlId": "MASVS-NETWORK-1", + "version": "2", + "__typename": "ComplianceReportRelation" + } + ], + "__typename": "Finding" + }, + { + "affected": true, + "checkId": "apk_webview_access", + "uniqueVulnerabilityId": 2802571, + "check": { + "id": "apk_webview_access", + "analysisType": "static", + "title": "WebViews Allowing Access to Local Files", + "description": "This check statically analyzes the app looking for WebViews configured to allow file access using specific methods from the [android.webkit.WebSettings](https://developer.android.com/reference/android/webkit/WebSettings.html) class.\n\nIt also considers the app's `minSdkVersion` from the `AndroidManifest.xml`, which determines default values for WebView file access methods as follows:\n\n- [`setAllowFileAccess`](): `True` when the app's `minSdkVersion` <= 29\n- [`setAllowFileAccessFromFileURLs`](): `True` when the app's `minSdkVersion` <= 15\n- [`setAllowUniversalAccessFromFileURLs`](): `True` when the app's `minSdkVersion` <= 15\n\nThis finding is triggered when the following criteria are met for a WebView:\n\n1. It has file access enabled by default (due to the `minSdkVersion`) or explicitly by using the above methods.\n2. It has JavaScript enabled due to the use of `setJavaScriptEnabled(true)`.", + "shortDescription": "Allowing WebViews to access local files can lead to unauthorized access or manipulation by attackers. If executable code or scripts are available locally, attackers could inject and execute malicious code, resulting in exposure of configuration files, cached data, credentials, or other sensitive information, potentially leading to significant data breaches and compromised user privacy.", + "platformType": "android", + "category": "platform", + "categories": [ + "Platform Interaction" + ], + "legacyFindingKey": "apk_webview_access", + "isNew": false, + "deprecated": false, + "context": { + "view": "table", + "title": "Methods allowing local resource access in WebViews", + "fields": [ + { + "key": "local_resource_access_method", + "format": null, + "title": "Access Method", + "description": "the method allowing access to local resources", + "__typename": "FindingContextField" + }, + { + "key": "default_used", + "format": null, + "title": "Uses SDK Default", + "description": "states if the Android SDK version's default value was used", + "__typename": "FindingContextField" + }, + { + "key": "value", + "format": null, + "title": "Value", + "description": "the boolean value passed to the access method", + "__typename": "FindingContextField" + }, + { + "key": "source_file", + "format": null, + "title": "Source File", + "description": "the file where the access method was used", + "__typename": "FindingContextField" + }, + { + "key": "package_name", + "format": null, + "title": "Package Name", + "description": "the package containing the access method", + "__typename": "FindingContextField" + }, + { + "key": "class_name", + "format": null, + "title": "Class", + "description": "the class using the access method", + "__typename": "FindingContextField" + }, + { + "key": "method", + "format": null, + "title": "Method", + "description": "the method using the access method", + "__typename": "FindingContextField" + } + ], + "children": null, + "__typename": "FindingContextMetadata" + }, + "issue": { + "cvss": 7.5, + "cvssVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:L", + "title": "WebViews Allowing Access to Local Files", + "description": "Some WebViews were detected with access to local files.\n\nWebViews are components used to display web content within a mobile app. If improperly configured, WebViews can provide access to local files stored on the device or sensitive app data. This access occurs because WebViews can load content from multiple sources, including the local file system. Without proper restrictions, an attacker could take advantage of this behavior to gain access to or manipulate local files, which could potentially compromise the security of the app and its users.", + "recommendation": "- **Access Method:** the method allowing access to local resources\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Value:** the boolean value passed to the access method\n- **Source File:** the file where the access method was used\n- **Package Name:** the package containing the access method\n- **Class:** the class using the access method\n- **Method:** the method using the access method\n\nWhen determining to remediate or dismiss this issue, consider the use case of the analyzed app as there are legitimate cases where enabling both local file access and JavaScript is necessary, such as hybrid apps, apps that display interactive local HTML content for offline use (e.g. e-book readers), offline documentation apps, or educational tools. In these situations, ensure all local files are trusted and properly secured to minimize potential security risks.\n\nOtherwise, please follow these recommendations:\n\nIf **Uses SDK Default** is `false`, the identified method is explicitly called in the app's code or libraries. In this case, update the method calls to disable file access, for example, by changing `setAllowFileAccess(true)` to `setAllowFileAccess(false)`.\n\nIf **Uses SDK Default** is `true`, the identified WebView uses insecure default `WebSettings` values. WebView settings change based on the app's `minSdkVersion` declared in the Android Manifest. To ensure secure settings are used, you can either update AndroidManifest.xml by setting `minSdkVersion` to 30 or higher, which changes the default `WebSettings` to more secure values, or explicitly set secure values in the code. This can be done by locating the insecure WebView and manually applying secure settings, for example, by calling `webView.getSettings().setAllowFileAccess(false)`.\n\nIf the **Value** is ``, then the flagged method was not provided an explicit `true` or `false` value. In this case, each of these methods must be reviewed manually to determine that the parameter passed to the method is secure. For example, if `setAllowFileAccess(flag)` was found, ensure that `flag` is set to `false` prior to the method being called.\n\n**Locating the finding:** Use the provided values for **Source File**, **Package Name**, **Class**, **Method** as well as the additional location data (if available) to determine the source of the offending code. If the issue originates from a third-party library, try updating the library or using a different one. If this isn't possible or the issue persists, carefully analyze how the app uses the identified WebViews and report the issue to the library maintainers.\n\nSome additional mitigations include:\n\n- Validating and sanitizing all content loaded into WebViews.\n- Avoid using `setAllowFileAccessFromFileURLs` or `setAllowUniversalAccessFromFileURLs` for accessing local content. Instead, use [WebViewAssetLoader](https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader).\n- Ensuring that exported activities handling Intents validate input URIs and implementing intent-filters to accept only trusted sources.\n- Validating URLs used in WebViews using [shouldOverrideUrlLoading](https://developer.android.com/reference/android/webkit/WebViewClient#shouldOverrideUrlLoadingandroid.webkit.WebView,%20android.webkit.WebResourceRequest).\n- Enforcing HTTPS for all content loaded into the WebView and ensure correct TLS implementation to prevent MITM attacks.\n- Validating inputs to any existing [JavaScript Interfaces to client-side Android code](https://developer.android.com/develop/ui/views/layout/webapps/webview#BindingJavaScript).", + "passingContent": "No WebViews were detected with access to local files.", + "category": null, + "severity": "high", + "warn": false, + "impactSummary": "If local files contain executable code or scripts, an attacker could exploit the WebView to inject and execute malicious code, which could then result in unauthorized access to sensitive local resources such as configuration files, cached data, user credentials, tokens, or personal information stored in the app's directory, potentially leading to data breaches.\n\nSome common scenarios include:\n\n- **Man-in-the-middle (MITM) Attacks**: If the WebView loads content over unsecured connections (e.g., HTTP), an attacker on the same network can intercept and modify the data in transit by injecting malicious scripts or code into the intercepted content, allowing the WebView to execute that code and potentially access sensitive data or local resources.\n- **Exploitation via Exported Components**: If the app has exported activities that accept Intents to load URLs in a WebView without proper validation, an attacker could craft an Intent to load malicious content or local files, potentially leading to data leakage or code execution.\n- **Loading Untrusted or User-Generated Content**: If the WebView loads content from user input or external sources without proper validation or sanitization, it can allow attackers to provide crafted input containing malicious scripts or code that the WebView processes, resulting in code execution within the context of the app.\n- **Exploitation via External Storage**: If the app loads resources from external storage without verifying their integrity or origin, it may allow attackers to place malicious files in external storage that the WebView accesses, resulting in the execution of malicious code within the app.", + "regulations": [ + { + "type": "owasp", + "label": "Risk OWASP", + "links": [ + { + "title": "MSTG-PLATFORM-6 (OWASP MASVS v1.5.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v1.5.0/Document/0x11-V6-Interaction_with_the_environment.md", + "__typename": "RegulatoryLink" + }, + { + "title": "MASVS-PLATFORM-2 (OWASP MASVS v2.1.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v2.1.0/controls/MASVS-PLATFORM-2.md", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + } + ], + "stepsToReproduce": null, + "codeSamples": null, + "guidanceLinks": [ + { + "platform": "android", + "caption": "OWASP MASTG - Testing WebView Protocol Handlers", + "url": "https://mas.owasp.org/MASTG/tests/android/MASVS-PLATFORM/MASTG-TEST-0032", + "__typename": "IssueGuidanceLink" + }, + { + "platform": "android", + "caption": "Android Developers - WebSettings", + "url": "https://developer.android.com/reference/android/webkit/WebSettings.html", + "__typename": "IssueGuidanceLink" + } + ], + "__typename": "FindingIssue" + }, + "compliance": null, + "__typename": "FindingCheck" + }, + "userChanges": null, + "cvss": 7.5, + "cvssVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:L", + "findingStatus": "detected", + "decision": "NONE", + "decisionInfo": null, + "evidenceDecision": "NONE", + "hidden": false, + "impactType": "high", + "severity": "high", + "note": null, + "adjustments": [], + "shortRemediation": null, + "title": "WebViews Allowing Access to Local Files", + "hasContext": true, + "hasCodeLocations": true, + "canHaveActionableEvidence": true, + "hasActionedEvidence": false, + "policyCategory": { + "policyCategory": 1, + "color": "#CA1108", + "label": "Needs Remediation", + "__typename": "PolicyCategory" + }, + "policyFindingOverrides": { + "checkId": "apk_webview_access", + "cvss": 7.5, + "cvssVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:L", + "hidden": false, + "impactType": "high", + "__typename": "PolicyFinding" + }, + "complianceReportRelations": [ + { + "catalog": "MASVS", + "groupId": "MASVS-PLATFORM", + "controlId": "MSTG-PLATFORM-6", + "version": "1", + "__typename": "ComplianceReportRelation" + }, + { + "catalog": "MASVS", + "groupId": "MASVS-PLATFORM", + "controlId": "MASVS-PLATFORM-2", + "version": "2", + "__typename": "ComplianceReportRelation" + } + ], + "__typename": "Finding" + }, + { + "affected": true, + "checkId": "openssl_cve_2023_0286", + "uniqueVulnerabilityId": 2802566, + "check": { + "id": "openssl_cve_2023_0286", + "analysisType": "static", + "title": "Dependent OpenSSL Library Vulnerable to CVE-2023-0286", + "description": "This test retrieves the list of software components for the app and checks if it contains versions of the OpenSSL library vulnerable to CVE-2023-0286.", + "shortDescription": "Using a vulnerable version of the OpenSSL library affected by CVE-2023-0286 may allow attackers to read sensitive memory contents due to improper handling of X.509 GeneralName fields. This type confusion vulnerability can potentially lead to security breaches and unauthorized access to sensitive data.", + "platformType": null, + "category": "code", + "categories": [ + "Code Quality" + ], + "legacyFindingKey": "openssl_cve_2023_0286", + "isNew": false, + "deprecated": true, + "context": { + "view": "table", + "title": "OpenSSL Libs Vulnerable to CVE-2023-0286 Found", + "fields": [ + { + "key": "version", + "format": null, + "title": "Version", + "description": "vulnerable version.", + "__typename": "FindingContextField" + }, + { + "key": "source", + "format": null, + "title": "Source", + "description": "path within your app package file where the vulnerable version was found.", + "__typename": "FindingContextField" + } + ], + "children": null, + "__typename": "FindingContextMetadata" + }, + "issue": { + "cvss": 7.4, + "cvssVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:H", + "title": "Dependent OpenSSL Library Vulnerable to CVE-2023-0286", + "description": "The app contains a version of the OpenSSL library vulnerable to CVE-2023-0286.\n\n[CVE-2023-0286](https://nvd.nist.gov/vuln/detail/CVE-2023-0286) is a type confusion vulnerability where OpenSSL processes an X.509 GeneralName containing an X.400 Address. The X.400 Address is then assigned the wrong data type and stored as an `ANS1_TYPE` instead of `ANS1_STRING`. This allows attackers to read the contents of memory addresses by passing pointers to `memcmp` when calls to this function are taking place during certificate revocation list validation.", + "recommendation": "The evidence table shows versions of OpenSSL vulnerable to CVE-2023-0286:\n\n- **Version:** vulnerable version.\n- **Source:** path within your app package file where the vulnerable version was found.\n\nIt is important to remember the following when evaluating this finding:\n\n- The affected instances might be a direct package dependency of your app or a dependency of a third-party library included in your project. If that's the case, update the third-party library or use a different one.\n- The CVSS score is predetermined by the associated CVEs without considering the context of any specific app. This means the way your app interacts with this library may mitigate the risks considered in the CVSS score.\n\nUpdate the version of all vulnerable instances of the OpenSSL library by completing the following recommendations:\n\n- If the `version` found is between `1.0.2 - 1.0.2zf` please upgrade to `1.0.2zg`.\n- If the `version` found is between `1.1.1 - 1.1.1q` please upgrade to `1.1.1t`.\n- If the `version` found is between `3.0.0 - 3.0.7` please upgrade to `3.0.8`.\n\n**Note**: If SQLCipher is one of your dependencies please note that it currently has a vulnerable version of OpenSSL v1.1.1q. However the maintainers state that [SQLCipher is not affected by this cve because SQLCipher does not use the X.509 features of OpenSSL](https://github.com/sqlcipher/android-database-sqlcipher/issues/622#issuecomment-1501789797).", + "passingContent": "The app does not contain a version of the OpenSSL library vulnerable to CVE-2023-0286.", + "category": "code", + "severity": "high", + "warn": false, + "impactSummary": "An attacker may use this vulnerability to access values at any specified memory address. Sensitive information can potentially be accessed. However, it should be noted that in order for this attack to be carried out, a few criteria must be met. The criteria may make this vector of attack much more uncommon and difficult to carry out compared to other well-known critical bugs, such as [\"heartbleed\"](https://heartbleed.com/). These prerequisites and mitigating factors limit its usefulness to attackers.", + "regulations": [ + { + "type": "owasp", + "label": "Risk OWASP", + "links": [ + { + "title": "MSTG-CODE-5 (OWASP MASVS v1.5.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v1.5.0/Document/0x12-V7-Code_quality_and_build_setting_requirements.md", + "__typename": "RegulatoryLink" + }, + { + "title": "MASVS-CODE-3 (OWASP MASVS v2.1.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v2.1.0/controls/MASVS-CODE-3.md", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + } + ], + "stepsToReproduce": null, + "codeSamples": null, + "guidanceLinks": [ + { + "platform": null, + "caption": "NIST Common Vulnerability Listing for CVE-2023-0286", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-0286", + "__typename": "IssueGuidanceLink" + }, + { + "platform": null, + "caption": "OWASP MASTG - Checking for Weaknesses in Third Party Libraries (MSTG-CODE-5, Android)", + "url": "https://github.com/OWASP/owasp-mastg/blob/v1.5.0/Document/0x05i-Testing-Code-Quality-and-Build-Settings.md#checking-for-weaknesses-in-third-party-libraries-mstg-code-5", + "__typename": "IssueGuidanceLink" + }, + { + "platform": null, + "caption": "OWASP MASTG - Checking for Weaknesses in Third Party Libraries (MSTG-CODE-5, iOS)", + "url": "https://github.com/OWASP/owasp-mastg/blob/v1.5.0/Document/0x06i-Testing-Code-Quality-and-Build-Settings.md#checking-for-weaknesses-in-third-party-libraries-mstg-code-5", + "__typename": "IssueGuidanceLink" + } + ], + "__typename": "FindingIssue" + }, + "compliance": null, + "__typename": "FindingCheck" + }, + "userChanges": null, + "cvss": 7.4, + "cvssVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:H", + "findingStatus": "detected", + "decision": "NONE", + "decisionInfo": null, + "evidenceDecision": "NONE", + "hidden": false, + "impactType": "high", + "severity": "high", + "note": null, + "adjustments": [], + "shortRemediation": null, + "title": "Dependent OpenSSL Library Vulnerable to CVE-2023-0286", + "hasContext": true, + "hasCodeLocations": false, + "canHaveActionableEvidence": true, + "hasActionedEvidence": false, + "policyCategory": { + "policyCategory": 1, + "color": "#CA1108", + "label": "Needs Remediation", + "__typename": "PolicyCategory" + }, + "policyFindingOverrides": { + "checkId": "openssl_cve_2023_0286", + "cvss": 7.4, + "cvssVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:H", + "hidden": false, + "impactType": "high", + "__typename": "PolicyFinding" + }, + "complianceReportRelations": [ + { + "catalog": "MASVS", + "groupId": "MASVS-CODE", + "controlId": "MSTG-CODE-5", + "version": "1", + "__typename": "ComplianceReportRelation" + }, + { + "catalog": "MASVS", + "groupId": "MASVS-CODE", + "controlId": "MASVS-CODE-3", + "version": "2", + "__typename": "ComplianceReportRelation" + } + ], + "__typename": "Finding" + }, + { + "affected": true, + "checkId": "on_received_ssl_error_proceed", + "uniqueVulnerabilityId": 2802560, + "check": { + "id": "on_received_ssl_error_proceed", + "analysisType": "static", + "title": "Insecure Implementation of WebView SSL Error Can Expose Network Traffic to Interception and Modification", + "description": "The Android `WebviewClient` class can notify the host application whenever a recoverable SSL certificate error occurs while loading a resource using the onReceivedSslError method call. On receiving this error, the host application can do one of two things - call `SslErrorHandler.cancel()` or `SslErrorHandler.proceed()`. The default (and recommended) behavior is to cancel the load. Applications can choose to proceed past the SSL error however using `SslErrorHandler.proceed()`. This test checks for instances where the application proceeds past SSL errors received by the WebViewClient.", + "shortDescription": "Using `SslErrorHandler.proceed()` can lead to ignoring SSL certificate errors, making the application vulnerable to man-in-the-middle attacks. This allows attackers to modify web content, steal sensitive data, and execute arbitrary code, potentially resulting in security alerts from Google Play Store.", + "platformType": "android", + "category": "code", + "categories": [ + "Networking" + ], + "legacyFindingKey": "on_received_ssl_error_proceed", + "isNew": false, + "deprecated": false, + "context": { + "view": "table", + "title": "Proceeds past SSL errors", + "fields": [ + { + "key": "method", + "format": "method", + "title": "Location in Code", + "description": null, + "__typename": "FindingContextField" + } + ], + "children": null, + "__typename": "FindingContextMetadata" + }, + "issue": { + "cvss": 5.9, + "cvssVector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N", + "title": "Insecure Implementation of WebView SSL Error Can Expose Network Traffic to Interception and Modification", + "description": "The app is using `SslErrorHandler.proceed()`, an unsafe implementation of `WebViewClient.onReceivedSslError` that ignores all SSL certificate validation errors and leaves the app vulnerable to man-in-the-middle attacks.\nIts use can allow an attacker to modify the content of the affected WebView, steal sensitive transmitted data, and execute code inside the app. The use of `SslErrorHandler.proceed()` typically results in a security alert from Google that prevents the app from being uploaded to the Play Store.", + "recommendation": "Unsafe network error handling in Android WebViews can allow an app to make an insecure connection. Apps should never allow users to bypass network security controls or have the app written in such a way that allows the app to create connections that ignore security alerts.\nThese high risk scenarios can be avoided by properly implementing the call `SslErrorHandler.cancel()` to cancel the load when a SSL error is received by the WebviewClient.", + "passingContent": null, + "category": null, + "severity": "medium", + "warn": false, + "impactSummary": "Applications that implement improper error handling with Webview network security controls can have network communications intercepted.\nA Webview is an in-app browser and is used to serve arbitrary content to users in the same way that a browser would. This makes vulnerabilities in WebViews especially broad as these issues can not only affect the app itself, but also create issues for the content loaded by the app's functionality.\nAn attacker who is able to exploit this vulnerability may use arbitrary code as a vector for follow-on attacks that lead to loss or change of sensitive user information as well as displaying malicious or offensive content in the app.", + "regulations": [ + { + "type": "owasp", + "label": "Risk OWASP", + "links": [ + { + "title": "MSTG-NETWORK-1 (OWASP MASVS v1.5.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v1.5.0/Document/0x10-V5-Network_communication_requirements.md", + "__typename": "RegulatoryLink" + }, + { + "title": "MASVS-NETWORK-1 (OWASP MASVS v2.1.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v2.1.0/controls/MASVS-NETWORK-1.md", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + } + ], + "stepsToReproduce": "Verify Webview code contains proper error handling measures as described in the Recommended Fix section.\nThe NowSecure automated test for this vulnerability identifies instances where the application proceeds past SSL errors received by the WebViewClient.", + "codeSamples": [ + { + "platform": "android", + "syntax": "java", + "caption": "Good Code Example", + "block": "public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error){\nString message = \"\";\nswitch(error.getPrimaryError()){\n case SslError.SSL_UNTRUSTED:\n message = \"The certificate is not trusted\";\n Log.e(\"Ssl Certificate error found: \"+message);\n handler.cancel();\n break;\n //... do this for the SsLError constants you would like to check for\n}\n}\n\n// The SslError constants are up to you to decide if the server you are connecting to meets your expectations or does not.\n// We simply log the message as an error for reference and do not allow the user to proceed.", + "__typename": "IssueCodeSample" + }, + { + "platform": "android", + "syntax": "kotlin", + "caption": "Good Code Example", + "block": "fun onReceivedSslError(view: WebView?, handler: SslErrorHandler, error: SslError) {\nvar message: String = \"\"\n when (error.primaryError) {\n SslError.SSL_UNTRUSTED -> {\n message = \"The certificate is not trusted\"\n Log.e(\"Ssl Certificate error found: $message\")\n handler.cancel()\n }\n //... do this for the SsLError constants you would like to check for\n }\n}\n\n// The SslError constants are up to you to decide if the server you are connecting to meets your expectations or does not.\n// We simply log the message as an error for reference and do not allow the user to proceed.", + "__typename": "IssueCodeSample" + } + ], + "guidanceLinks": [ + { + "platform": "android", + "caption": "This article describes the callback that an app receives when an SSL error occurs", + "url": "https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedSslError(android.webkit.WebView,%20android.webkit.SslErrorHandler,%20android.net.http.SslError)", + "__typename": "IssueGuidanceLink" + }, + { + "platform": "android", + "caption": "This documentation contains a description of the SslError class containing the type of error and the SSL certificate", + "url": "https://developer.android.com/reference/android/net/http/SslError", + "__typename": "IssueGuidanceLink" + } + ], + "__typename": "FindingIssue" + }, + "compliance": null, + "__typename": "FindingCheck" + }, + "userChanges": null, + "cvss": 5.9, + "cvssVector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N", + "findingStatus": "detected", + "decision": "NONE", + "decisionInfo": null, + "evidenceDecision": "NONE", + "hidden": false, + "impactType": "medium", + "severity": "medium", + "note": null, + "adjustments": [], + "shortRemediation": null, + "title": "Insecure Implementation of WebView SSL Error Can Expose Network Traffic to Interception and Modification", + "hasContext": true, + "hasCodeLocations": false, + "canHaveActionableEvidence": true, + "hasActionedEvidence": false, + "policyCategory": { + "policyCategory": 1, + "color": "#CA1108", + "label": "Needs Remediation", + "__typename": "PolicyCategory" + }, + "policyFindingOverrides": { + "checkId": "on_received_ssl_error_proceed", + "cvss": 5.9, + "cvssVector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N", + "hidden": false, + "impactType": "medium", + "__typename": "PolicyFinding" + }, + "complianceReportRelations": [ + { + "catalog": "MASVS", + "groupId": "MASVS-NETWORK", + "controlId": "MSTG-NETWORK-1", + "version": "1", + "__typename": "ComplianceReportRelation" + }, + { + "catalog": "MASVS", + "groupId": "MASVS-NETWORK", + "controlId": "MASVS-NETWORK-1", + "version": "2", + "__typename": "ComplianceReportRelation" + } + ], + "__typename": "Finding" + }, + { + "affected": true, + "checkId": "keysize_check", + "uniqueVulnerabilityId": 2802539, + "check": { + "id": "keysize_check", + "analysisType": "static", + "title": "Key Used to Publish App is Potentially Forgeable", + "description": "This test checks that all keys used to sign the app are larger than 1024 bits.", + "shortDescription": "Usage of signing keys shorter than 1024 bits can lead to vulnerabilities from brute force attacks on digital signatures, exposing the app to forged updates, malware injection, or reputational damage.", + "platformType": "android", + "category": "code", + "categories": [ + "Resilience" + ], + "legacyFindingKey": "keysize_check", + "isNew": false, + "deprecated": false, + "context": { + "view": "table", + "title": "Insecure Keys", + "fields": [ + { + "key": "key_size", + "format": null, + "title": "Key Size", + "description": null, + "__typename": "FindingContextField" + }, + { + "key": "key_type", + "format": null, + "title": "Key Type", + "description": null, + "__typename": "FindingContextField" + }, + { + "key": "issuer", + "format": null, + "title": "Issuer", + "description": null, + "__typename": "FindingContextField" + } + ], + "children": null, + "__typename": "FindingContextMetadata" + }, + "issue": { + "cvss": 5.9, + "cvssVector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N", + "title": "Key Used to Publish App is Potentially Forgeable", + "description": "At least one key that was used to sign the app is too short to be considered secure.\n\nThe application was signed using a key length less than or equal to 1024 bits, making it potentially vulnerable to brute force attacks resulting in forged digital signatures. An attacker requires significantly less time to brute force a signing key with a short key length. Insecure keys can be exploited to inject malware into trusted versions of apps, publish updates that will be accepted by the OS as valid, or tarnish the publisher's brand.\n\nThe `minSdkVersion` of an app, indicated in the AndroidManifest.xml, determines the signing version that will be used. The signing version specifies the key length that is used during the signing process.\n\n- [v2 Android 7.0 (API level 24)](https://source.android.com/docs/security/features/apksigning/v2)\n- [v3 Android 9 (API level 28)](https://source.android.com/docs/security/features/apksigning/v3)\n- [v4 Android 11 (API level 30)](https://source.android.com/docs/security/features/apksigning/v4)\n\nFor example, if your app supports `minSdkVersion` of 24 and is installed on Android 7.0 device, it will use an insecure v2 signing version for verification.", + "recommendation": "You can use [Keytool](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html) to verify the length of your keys with `keytool -list -v -keystore `.\n\nFor optimal protection, apps should be signed by a key with a length of at least 2048 (preferably 4096) bits. You can [use Keytool](https://developer.android.com/studio/publish/app-signing) with the `-keysize ` parameter to specify a key length longer than the 1024-bit default. For apps that have already been signed, updating the key will require [key rotation](https://support.google.com/googleplay/android-developer/answer/9842756?hl=en).", + "passingContent": "The app wasn't signed with keys having a key size considered weak.", + "category": null, + "severity": "medium", + "warn": false, + "impactSummary": "Apps with forged signing keys can be used as a vector for fraud and phishing attacks which can have significant reputational impact. An attacker can use leverage forged app updates to modify an app without the developer's consent.", + "regulations": [ + { + "type": "cwe", + "label": "CWE", + "links": [ + { + "title": "310", + "url": "https://cwe.mitre.org/data/definitions/310.html", + "__typename": "RegulatoryLink" + }, + { + "title": "326", + "url": "https://cwe.mitre.org/data/definitions/326.html", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "niap", + "label": "NIAP", + "links": [ + { + "title": "FPT_TUD_EXT.1.6", + "url": "https://www.niap-ccevs.org/MMO/PP/-429-M-/pp_app_v1.3_table-reqs.htm#FPT_TUD_EXT.1.6", + "__typename": "RegulatoryLink" + }, + { + "title": "FCS_COP.1.1(3)", + "url": "https://www.niap-ccevs.org/MMO/PP/-429-M-/pp_app_v1.3_table-reqs.htm#FCS_COP.1.1(3)", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "fisma_low", + "label": "FISMA LOW", + "links": [ + { + "title": "SC-13 CRYPTOGRAPHIC PROTECTION", + "url": "https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=SC-13", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "fisma_med", + "label": "FISMA MED", + "links": [ + { + "title": "SI-7 SOFTWARE, FIRMWARE, AND INFORMATION INTEGRITY", + "url": "https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=SI-7", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "owasp", + "label": "Risk OWASP", + "links": [ + { + "title": "MSTG-CODE-1 (OWASP MASVS v1.5.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v1.5.0/Document/0x12-V7-Code_quality_and_build_setting_requirements.md", + "__typename": "RegulatoryLink" + }, + { + "title": "MASVS-RESILIENCE-2 (OWASP MASVS v2.1.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v2.1.0/controls/MASVS-RESILIENCE-2.md", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "gdpr", + "label": "GDPR", + "links": [ + { + "title": "Risks violating Article 25", + "url": "https://gdpr-info.eu/art-25-gdpr/", + "__typename": "RegulatoryLink" + }, + { + "title": "Risks violating Article 32", + "url": "https://gdpr-info.eu/art-32-gdpr/", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "ffiec", + "label": "FFIEC", + "links": [ + { + "title": "May violate D3.PC.Se.Int.3", + "url": "https://www.ffiec.gov/pdf/cybersecurity/FFIEC_CAT_May_2017.pdf", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "pci", + "label": "PCI", + "links": [ + { + "title": "May violate requirement 3.6.1", + "url": "https://www.pcisecuritystandards.org/document_library?document=pci_dss", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "hipaa", + "label": "HIPAA", + "links": [ + { + "title": "May violate ยง164.312(a)(1): Standard: Access control.", + "url": "https://www.hhs.gov/sites/default/files/ocr/privacy/hipaa/administrative/securityrule/techsafeguards.pdf?language=es", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "ccpa", + "label": "CCPA", + "links": [ + { + "title": "Risks violating CCPA: exfiltration, theft, or disclosure of PII", + "url": "https://cdp.cooley.com/ccpa-2018/#section-1798-150", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "cwe_top_25", + "label": "CWE Top 25", + "links": [ + { + "title": "2021 CWE Top 25 Most Dangerous Software Errors", + "url": "https://cwe.mitre.org/top25/archive/2021/2021_cwe_top25.html", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + } + ], + "stepsToReproduce": null, + "codeSamples": [ + { + "platform": "android", + "syntax": "bash", + "caption": "Key Replacement Process", + "block": "In order to replace the key of an app that has already been created, a rotation must be done (this is a linked list of previous certs to tell other applications this new one can be trusted). Once it has been generated the new key must be added to the Google Play console to ensure that future builds that contain the new cert are accepted by the Play Store and app.\n\nFrom Command Line\nApp Key Generation:\n$ keytool -genkey -v -keystore my-key.keystore -alias alias_name -keyalg RSA -keysize 4096 -validity 10000\n\nDebug Key Generation:\n$ keytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 4096 -validity 10000", + "__typename": "IssueCodeSample" + } + ], + "guidanceLinks": [ + { + "platform": "android", + "caption": "Android Developer Documentation - Sign your app for release to Google Play", + "url": "https://developer.android.com/studio/publish/app-signing#generate-key", + "__typename": "IssueGuidanceLink" + }, + { + "platform": "android", + "caption": "Google Play - Instructions for apps created before August 2021", + "url": "https://support.google.com/googleplay/android-developer/answer/9842756?hl=en#zippy=%2Cinstructions-for-apps-created-before-august", + "__typename": "IssueGuidanceLink" + }, + { + "platform": "android", + "caption": "Google Play - Upgrade your app signing key", + "url": "https://support.google.com/googleplay/android-developer/answer/9842756?hl=en#upgrade", + "__typename": "IssueGuidanceLink" + }, + { + "platform": "android", + "caption": "Google Play - App Signing Best Practices", + "url": "https://support.google.com/googleplay/android-developer/answer/9842756?hl=en#best", + "__typename": "IssueGuidanceLink" + } + ], + "__typename": "FindingIssue" + }, + "compliance": null, + "__typename": "FindingCheck" + }, + "userChanges": null, + "cvss": 5.9, + "cvssVector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N", + "findingStatus": "detected", + "decision": "NONE", + "decisionInfo": null, + "evidenceDecision": "NONE", + "hidden": false, + "impactType": "medium", + "severity": "medium", + "note": null, + "adjustments": [], + "shortRemediation": null, + "title": "Key Used to Publish App is Potentially Forgeable", + "hasContext": true, + "hasCodeLocations": false, + "canHaveActionableEvidence": false, + "hasActionedEvidence": false, + "policyCategory": { + "policyCategory": 1, + "color": "#CA1108", + "label": "Needs Remediation", + "__typename": "PolicyCategory" + }, + "policyFindingOverrides": { + "checkId": "keysize_check", + "cvss": 5.9, + "cvssVector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N", + "hidden": false, + "impactType": "medium", + "__typename": "PolicyFinding" + }, + "complianceReportRelations": [ + { + "catalog": "MASVS", + "groupId": "MASVS-CODE", + "controlId": "MSTG-CODE-1", + "version": "1", + "__typename": "ComplianceReportRelation" + }, + { + "catalog": "MASVS", + "groupId": "MASVS-RESILIENCE", + "controlId": "MASVS-RESILIENCE-2", + "version": "2", + "__typename": "ComplianceReportRelation" + } + ], + "__typename": "Finding" + } + ], + "__typename": "AssessmentReport" + }, + "baseReport": { + "findings": [ + { + "checkId": "apk_insecure_network_config", + "affected": true, + "cvss": 7.5, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_webview_access", + "affected": true, + "cvss": 7.5, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "openssl_cve_2023_0286", + "affected": true, + "cvss": 7.4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "on_received_ssl_error_proceed", + "affected": true, + "cvss": 5.9, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "keysize_check", + "affected": false, + "cvss": 5.9, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "libcurl", + "affected": false, + "cvss": 5.7, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_custom", + "affected": false, + "cvss": 4.4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "unprotected_context_registered_broadcast_receivers", + "affected": false, + "cvss": 4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "unprotected_manifest_broadcast_receivers", + "affected": false, + "cvss": 4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "libraries_ssp", + "affected": false, + "cvss": 1.6, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_hashing_algorithms", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_deeplinks", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "vulnerable_libraries", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "hardcoded_passwords", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_strandhogg", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_insecure_prng", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_network_config_exceptions", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "android_ssl_vuln", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_intent_redirection", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_hardcoded_secrets", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_device_or_other_ids_collected", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "ai_use_on_device", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "api_hsts", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_textfield_autocorrect", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_certificate_pinning", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_flow", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "zip_file_in_transit_check_https", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_firebase_mfa_not_used", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "kotlin_debug_lib", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_insecure_constants", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "android_debuggable_webviews", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "hardcoded_api_keys", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "javascript_interface_check", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_dangerous_permissions", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "url_listing", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_crypto_keys", + "affected": null, + "cvss": null, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "sms_communications", + "affected": null, + "cvss": null, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "unsigned_jwt", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "sdcard_file_list", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_sqlcipher", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_application_servers", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_padding_oracle", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_iv_hardcoded", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "sql_injection", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "path_traversal", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "serialized_objects", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "arbitrary_code_execution_observed", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "android_static_iv", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_uses_vpn_permission", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "obfuscation_check", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "master_key_check", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "fragment_injection", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "secure_random_check", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "api_discovery", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_info", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "automation_info", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "behavioral_events", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_connection_domains", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_ivs", + "affected": false, + "cvss": null, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_tracking_domains", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_sensitive_data_pii", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "ai_libraries", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_build_info", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_nsc", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "get_app_files", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "app_sbom", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "snoop_network_hosts", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_sqlite", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "all_android_components", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_permissions", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "get_reflection_code", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_device_or_other_ids_shared", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_location_collected", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_location_shared", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_personal_info_collected", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_personal_info_shared", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "api_authentication", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "api_cors", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "cookie_without_httponly_flag", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "cookie_without_secure_flag", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_insufficient_rounds", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "runs_root_command", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "runs_root_command_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_iv_reuse", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_encryption_modes", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_iv_null", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_encryption_algorithms", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_root_detection_rasp", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "key_reuse", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_custom", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "certificate_validation", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "hostname_verification", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "uses_http", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "zip_file_in_transit_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_cert_validation", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_custom", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "zip_file_in_transit_check_broken_ssl", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "writable_executable_files_private_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "writable_executable_files_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "world_readable_files_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_sensitive_data_implicit_intents", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "ai_api_keys", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "world_writable_files_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "remote_code_execution", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "arbitrary_code_execution_probable", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_leaked_data_sdcard", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_custom", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_biometric_key_invalidation_disabled", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_janus_vuln", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "openssl_cve_2014_0224", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "openssl_cve_2014_0160", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "debug_flag_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_minimum_sdk", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_debug_symbols", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "joda_cve", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_ftp_libs", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_target_sdk_min", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "allow_backup_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "get_native_methods", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sqlcipher_key_leakage_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_blocker_apptentive", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "exported_components", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_janus_warn", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_libraries_aslr", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "okhttp", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "libpng_cve", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "play_services_basement", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "potential_sqlcipher_key_leakage_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_blocker_segment", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_in_app_updates", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "use_of_deprecated_xamarin", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "certificate_validity_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_vpn_always_on_not_available", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + } + ], + "__typename": "AssessmentReport" + } + }, + "__typename": "AutoQuery" + } + } +} diff --git a/unittests/scans/nowsecure/nowsecure_one_vul.json b/unittests/scans/nowsecure/nowsecure_one_vul.json deleted file mode 100644 index da8bda60f9d..00000000000 --- a/unittests/scans/nowsecure/nowsecure_one_vul.json +++ /dev/null @@ -1,2 +0,0 @@ -{"type":"auditAdvisory","data":{"resolution":{"id":1325,"path":"handlebars","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.5.2","paths":["handlebars"]}],"id":1325,"created":"2019-11-18T19:42:01.445Z","updated":"2020-02-26T17:55:51.120Z","deleted":null,"title":"Prototype Pollution","found_by":{"link":"","name":"Vladyslav Babkin","email":""},"reported_by":{"link":"","name":"Vladyslav Babkin","email":""},"module_name":"handlebars","cves":[],"vulnerable_versions":"<3.0.8 || >=4.0.0 <4.5.3","patched_versions":">=3.0.8 <4.0.0 || >=4.5.3","overview":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to prototype pollution. It is possible to add or modify properties to the Object prototype through a malicious template. This may allow attackers to crash the application or execute Arbitrary Code in specific conditions.","recommendation":"Upgrade to version 3.0.8, 4.5.3 or later.","references":"","access":"public","severity":"high","cwe":"CWE-471","metadata":{"module_type":"","exploitability":4,"affected_components":""},"url":"https://npmjs.com/advisories/1325"}}} -{"type":"auditSummary","data":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":1,"critical":0},"dependencies":47,"devDependencies":0,"optionalDependencies":0,"totalDependencies":47}} diff --git a/unittests/scans/nowsecure/nowsecure_one_vuln.json b/unittests/scans/nowsecure/nowsecure_one_vuln.json new file mode 100644 index 00000000000..79facbccab8 --- /dev/null +++ b/unittests/scans/nowsecure/nowsecure_one_vuln.json @@ -0,0 +1,2073 @@ +{ + "data": { + "auto": { + "assessment": { + "ref": "13371337-1337-1337-1337-133713371337", + "applicationRef": "73317331-7331-7331-7331-733173317331", + "platformType": "android", + "packageKey": "com.org.appname", + "packageVersion": "1.0.0", + "taskId": "1231231231231", + "title": "AppName", + "iconURL": "https://api.nowsecure.com/icon/hjfkjz9mxb3bxy3zi1ohraj60oqtpbw63wnvgon8l1ytt49dqwickoczrzopvkvb", + "isAppstoreDownload": false, + "createdAt": "2025-06-20T06:47:15.551Z", + "createdBy": { + "ref": "123123aa-129a-1223-ba11-129c91234asf", + "email": "user@email.com", + "name": "John Doe", + "__typename": "UserSummary" + }, + "buildRef": "123123aa-123a-1a31-123a-1231aa112311", + "buildVersion": "010000", + "upload": { + "ref": "1231acc1-123a-129f-19af-0aa123018391", + "createdAt": "2025-06-20T06:45:16.788Z", + "digest": "25tnhu7gc0u70lw9jnc120rilyz2z1blfnhssinqsgnvpjtvafj0x82ddfclyzri", + "__typename": "AutoUpload" + }, + "analysisConfigLevel": "BASELINE", + "type": "baseline", + "analysisJobType": "FULL", + "staticScore": null, + "score": 86.5, + "favorite": false, + "assessmentError": null, + "isDebugMode": false, + "hasPreviousAssessmentForComparison": false, + "policy": { + "ref": "1a11aa11-1111-1111-a111-11111aaa1111", + "name": "NowSecure Default Policy", + "createdBy": null, + "createdAt": "2022-07-06T11:04:26.575Z", + "updatedAt": "2025-08-20T16:25:34.128Z", + "archivedAt": null, + "targetType": "ORGANIZATION", + "isDefault": true, + "isNSManaged": true, + "latestVersion": { + "ref": "1111a11a-11aa-1aa1-1a1a-111a11111aa1", + "version": 60, + "trackedVersion": null, + "trackedVersionRef": null, + "__typename": "PolicyVersion" + }, + "targets": [ + { + "ref": "a1a111aa-111a-11aa-111a-11a111a1a1a1", + "type": "ORGANIZATION", + "__typename": "PolicyTarget" + } + ], + "enabled": true, + "trackedPolicy": null, + "__typename": "Policy" + }, + "policyVersion": { + "ref": "a11aa111-1a11-1111-1a1a-11aaa1a111a1", + "policyRef": "1a11aa11-1111-1111-a111-11111aaa1111", + "version": 56, + "policyCategories": [ + { + "policyCategory": 1, + "label": "Needs Remediation", + "description": "NowSecure suggests remediation", + "color": "#CA1108", + "__typename": "PolicyCategory" + }, + { + "policyCategory": 2, + "label": "Review Required", + "description": "NowSecure suggests security review to determine risk", + "color": "#FBA255", + "__typename": "PolicyCategory" + }, + { + "policyCategory": 3, + "label": "Informational", + "description": "NowSecure suggests general review for audit and information", + "color": "#0099ff", + "__typename": "PolicyCategory" + } + ], + "__typename": "PolicyVersion" + }, + "analysis": { + "isAuthenticated": null, + "isCancelled": false, + "isComplete": true, + "isRunning": false, + "status": "completed", + "mappedStatus": "completed", + "errorCode": null, + "error": null, + "artifacts": [ + { + "assessmentRef": "13371337-1337-1337-1337-133713371337", + "ref": "111111a1-1111-11aa-a11a-a111aa111a11", + "artifactType": "HAR", + "tags": "dynamic combined har", + "displayName": "Download artifact for Combined HAR", + "byteSize": 243826, + "filename": "combined.har", + "contentType": "application/json", + "url": "/v4/asset/artifact/13371337-1337-1337-1337-133713371337/111111a1-1111-11aa-a11a-a111aa111a11", + "__typename": "AnalysisArtifact" + } + ], + "screenshots": [ + { + "ref": "111111a1-a111-111a-11aa-1aa11111a1a1", + "url": "/v4/asset/screenshot/13371337-1337-1337-1337-133713371337/111111a1-a111-111a-11aa-1aa11111a1a1", + "analysisPass": 1, + "__typename": "AnalysisScreenshot" + }, + { + "ref": "1111a111-aaaa-1a1a-1a1a-a111a1a1a11a", + "url": "/v4/asset/screenshot/13371337-1337-1337-1337-133713371337/1111a111-aaaa-1a1a-1a1a-a111a1a1a11a", + "analysisPass": 1, + "__typename": "AnalysisScreenshot" + } + ], + "task": { + "static": { + "id": "1231231231231.static", + "status": "completed", + "modifiedAt": "2025-06-20T07:18:45.377Z", + "isRunning": false, + "isComplete": true, + "__typename": "AnalysisJob" + }, + "dynamic": { + "id": "1231231231231.dynamic", + "status": "completed", + "modifiedAt": "2025-06-20T07:18:36.233Z", + "isRunning": false, + "isComplete": true, + "__typename": "AnalysisJob" + }, + "__typename": "AnalysisTask" + }, + "__typename": "AutoAssessmentAnalysis" + }, + "build": { + "ref": "123123aa-123a-1a31-123a-1231aa112311", + "digest": "25tnhu7gc0u70lw9jnc120rilyz2z1blfnhssinqsgnvpjtvafj0x82ddfclyzri", + "version": "1.0.0", + "__typename": "AutoBuild" + }, + "group": { + "ref": "a111aaaa-aa11-11aa-1a11-11a111aa1111", + "__typename": "AutoGroup" + }, + "__typename": "AutoAssessment", + "report": { + "createdAt": "2025-06-20T06:47:15.551Z", + "findings": [ + { + "affected": true, + "checkId": "apk_insecure_network_config", + "uniqueVulnerabilityId": 2802557, + "check": { + "id": "apk_insecure_network_config", + "analysisType": "static", + "title": "App Configuration Allows Insecure Network Connections", + "description": "This check analyzes the app and looks for settings that allow cleartext traffic, such as `android:usesCleartextTraffic` in the `AndroidManifest.xml` file and `cleartextTrafficPermitted` in the Network Security Config file.", + "shortDescription": "Allowing insecure connections increases the risk of exposing sensitive data. Applications should explicitly disable cleartext communications, in order to avoid data interception or modification, which compromises sensitive information.", + "platformType": "android", + "category": "network", + "categories": [ + "Networking" + ], + "legacyFindingKey": "apk_insecure_network_config", + "isNew": false, + "deprecated": false, + "context": { + "view": "table", + "title": "Network Configurations Allowing Cleartext Traffic", + "fields": [ + { + "key": "source", + "format": null, + "title": "Source", + "description": "the file type that allows insecure access", + "__typename": "FindingContextField" + }, + { + "key": "xml_element", + "format": null, + "title": "XML Element", + "description": "the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)", + "__typename": "FindingContextField" + }, + { + "key": "xml_attribute", + "format": null, + "title": "XML Attribute", + "description": "the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)", + "__typename": "FindingContextField" + }, + { + "key": "default_used", + "format": null, + "title": "Uses SDK Default", + "description": "states if the Android SDK version's default value was used", + "__typename": "FindingContextField" + }, + { + "key": "allow_cleartext", + "format": null, + "title": "Allow Cleartext", + "description": "value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed", + "__typename": "FindingContextField" + }, + { + "key": "domain", + "format": null, + "title": "Domain", + "description": "the domain that allows cleartext data (only present if is used)", + "__typename": "FindingContextField" + }, + { + "key": "include_subdomains", + "format": null, + "title": "Includes Subdomains", + "description": "value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)", + "__typename": "FindingContextField" + } + ], + "children": null, + "__typename": "FindingContextMetadata" + }, + "issue": { + "cvss": 7.5, + "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", + "title": "App Configuration Allows Insecure Network Connections", + "description": "The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.", + "recommendation": "The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).", + "passingContent": "The app has no insecure settings allowing cleartext connections.", + "category": "network", + "severity": "high", + "warn": false, + "impactSummary": "Allowing cleartext network connections allows attackers to intercept, inspect or manipulate data transmitted between the app and external servers, compromising the integrity and confidentiality of user information. This vulnerability can have serious business implications, particularly in the event of a data breach, including loss of customer trust, potential legal liabilities and financial penalties.", + "regulations": [ + { + "type": "cwe", + "label": "CWE", + "links": [ + { + "title": "319", + "url": "https://cwe.mitre.org/data/definitions/319.html", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "fisma_low", + "label": "FISMA LOW", + "links": [ + { + "title": "SC-13 CRYPTOGRAPHIC PROTECTION", + "url": "https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=SC-13", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "fisma_med", + "label": "FISMA MED", + "links": [ + { + "title": "SC-8 TRANSMISSION CONFIDENTIALITY AND INTEGRITY", + "url": "https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=SC-8", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "owasp", + "label": "Risk OWASP", + "links": [ + { + "title": "MSTG-NETWORK-1 (OWASP MASVS v1.5.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v1.5.0/Document/0x10-V5-Network_communication_requirements.md", + "__typename": "RegulatoryLink" + }, + { + "title": "MASVS-NETWORK-1 (OWASP MASVS v2.1.0)", + "url": "https://github.com/OWASP/owasp-masvs/blob/v2.1.0/controls/MASVS-NETWORK-1.md", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "gdpr", + "label": "GDPR", + "links": [ + { + "title": "Risks violating Article 25", + "url": "https://gdpr-info.eu/art-25-gdpr/", + "__typename": "RegulatoryLink" + }, + { + "title": "Risks violating Article 32", + "url": "https://gdpr-info.eu/art-32-gdpr/", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "ffiec", + "label": "FFIEC", + "links": [ + { + "title": "May violate D3.PC.Am.Int.7", + "url": "https://www.ffiec.gov/pdf/cybersecurity/FFIEC_CAT_May_2017.pdf", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "pci", + "label": "PCI", + "links": [ + { + "title": "May violate requirement 4.1", + "url": "https://www.pcisecuritystandards.org/document_library?document=pci_dss", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "hipaa", + "label": "HIPAA", + "links": [ + { + "title": "May violate ยง164.312(e)(1): Standard: Transmission security.", + "url": "https://www.hhs.gov/sites/default/files/ocr/privacy/hipaa/administrative/securityrule/techsafeguards.pdf?language=es", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + }, + { + "type": "ccpa", + "label": "CCPA", + "links": [ + { + "title": "Risks violating CCPA: exfiltration, theft, or disclosure of PII", + "url": "https://cdp.cooley.com/ccpa-2018/#section-1798-150", + "__typename": "RegulatoryLink" + } + ], + "__typename": "RegulatoryRelation" + } + ], + "stepsToReproduce": null, + "codeSamples": [ + { + "platform": "android", + "syntax": "xml", + "caption": "Good Code Example", + "block": "\n\n \n\n", + "__typename": "IssueCodeSample" + } + ], + "guidanceLinks": [ + { + "platform": "android", + "caption": "Android Developer Documentation - Android Manifest", + "url": "https://developer.android.com/guide/topics/manifest/manifest-intro", + "__typename": "IssueGuidanceLink" + }, + { + "platform": "android", + "caption": "Android Developer Documentation - `usesCleartextTraffic` field", + "url": "https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic", + "__typename": "IssueGuidanceLink" + }, + { + "platform": "android", + "caption": "Android Developer Documentation - Network Security Config", + "url": "https://developer.android.com/privacy-and-security/security-config", + "__typename": "IssueGuidanceLink" + } + ], + "__typename": "FindingIssue" + }, + "compliance": null, + "__typename": "FindingCheck" + }, + "userChanges": null, + "cvss": 7.5, + "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", + "findingStatus": "detected", + "decision": "NONE", + "decisionInfo": null, + "evidenceDecision": "NONE", + "hidden": false, + "impactType": "high", + "severity": "high", + "note": null, + "adjustments": [], + "shortRemediation": null, + "title": "App Configuration Allows Insecure Network Connections", + "hasContext": true, + "hasCodeLocations": false, + "canHaveActionableEvidence": true, + "hasActionedEvidence": false, + "policyCategory": { + "policyCategory": 1, + "color": "#CA1108", + "label": "Needs Remediation", + "__typename": "PolicyCategory" + }, + "policyFindingOverrides": { + "checkId": "apk_insecure_network_config", + "cvss": 7.5, + "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", + "hidden": false, + "impactType": "high", + "__typename": "PolicyFinding" + }, + "complianceReportRelations": [ + { + "catalog": "MASVS", + "groupId": "MASVS-NETWORK", + "controlId": "MSTG-NETWORK-1", + "version": "1", + "__typename": "ComplianceReportRelation" + }, + { + "catalog": "MASVS", + "groupId": "MASVS-NETWORK", + "controlId": "MASVS-NETWORK-1", + "version": "2", + "__typename": "ComplianceReportRelation" + } + ], + "__typename": "Finding" + } + ], + "__typename": "AssessmentReport" + }, + "baseReport": { + "findings": [ + { + "checkId": "apk_insecure_network_config", + "affected": true, + "cvss": 7.5, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_webview_access", + "affected": false, + "cvss": 7.5, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "openssl_cve_2023_0286", + "affected": false, + "cvss": 7.4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "on_received_ssl_error_proceed", + "affected": false, + "cvss": 5.9, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "keysize_check", + "affected": false, + "cvss": 5.9, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "libcurl", + "affected": false, + "cvss": 5.7, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_custom", + "affected": false, + "cvss": 4.4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "unprotected_context_registered_broadcast_receivers", + "affected": false, + "cvss": 4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "unprotected_manifest_broadcast_receivers", + "affected": false, + "cvss": 4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "libraries_ssp", + "affected": false, + "cvss": 1.6, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_hashing_algorithms", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_deeplinks", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "vulnerable_libraries", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "hardcoded_passwords", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_strandhogg", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_insecure_prng", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_network_config_exceptions", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "android_ssl_vuln", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_intent_redirection", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_hardcoded_secrets", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_device_or_other_ids_collected", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "ai_use_on_device", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "api_hsts", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_textfield_autocorrect", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_certificate_pinning", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_flow", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "zip_file_in_transit_check_https", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_firebase_mfa_not_used", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "kotlin_debug_lib", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_insecure_constants", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "android_debuggable_webviews", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "hardcoded_api_keys", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "javascript_interface_check", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_dangerous_permissions", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "url_listing", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_crypto_keys", + "affected": null, + "cvss": null, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "sms_communications", + "affected": null, + "cvss": null, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "unsigned_jwt", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "sdcard_file_list", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_sqlcipher", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_application_servers", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_padding_oracle", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_iv_hardcoded", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "sql_injection", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "path_traversal", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "serialized_objects", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "arbitrary_code_execution_observed", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "android_static_iv", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_uses_vpn_permission", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "obfuscation_check", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "master_key_check", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "fragment_injection", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "secure_random_check", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "api_discovery", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_info", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "automation_info", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "behavioral_events", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_connection_domains", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_ivs", + "affected": false, + "cvss": null, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_tracking_domains", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_sensitive_data_pii", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "ai_libraries", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_build_info", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_nsc", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "get_app_files", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "app_sbom", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "snoop_network_hosts", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_sqlite", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "all_android_components", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_permissions", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "get_reflection_code", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_device_or_other_ids_shared", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_location_collected", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_location_shared", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_personal_info_collected", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_personal_info_shared", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "api_authentication", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "api_cors", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "cookie_without_httponly_flag", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "cookie_without_secure_flag", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_insufficient_rounds", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "runs_root_command", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "runs_root_command_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_iv_reuse", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_encryption_modes", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_iv_null", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_encryption_algorithms", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_root_detection_rasp", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "key_reuse", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_custom", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "certificate_validation", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "hostname_verification", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "uses_http", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "zip_file_in_transit_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_cert_validation", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_custom", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "zip_file_in_transit_check_broken_ssl", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "writable_executable_files_private_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "writable_executable_files_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "world_readable_files_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_sensitive_data_implicit_intents", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "ai_api_keys", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "world_writable_files_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "remote_code_execution", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "arbitrary_code_execution_probable", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_leaked_data_sdcard", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_custom", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_biometric_key_invalidation_disabled", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_janus_vuln", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "openssl_cve_2014_0224", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "openssl_cve_2014_0160", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "debug_flag_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_minimum_sdk", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_debug_symbols", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "joda_cve", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_ftp_libs", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_target_sdk_min", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "allow_backup_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "get_native_methods", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sqlcipher_key_leakage_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_blocker_apptentive", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "exported_components", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_janus_warn", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_libraries_aslr", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "okhttp", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "libpng_cve", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "play_services_basement", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "potential_sqlcipher_key_leakage_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_blocker_segment", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_in_app_updates", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "use_of_deprecated_xamarin", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "certificate_validity_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_vpn_always_on_not_available", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + } + ], + "__typename": "AssessmentReport" + } + }, + "__typename": "AutoQuery" + } + } +} diff --git a/unittests/scans/nowsecure/nowsecure_zero_vul.json b/unittests/scans/nowsecure/nowsecure_zero_vul.json deleted file mode 100644 index 38f53ef6e42..00000000000 --- a/unittests/scans/nowsecure/nowsecure_zero_vul.json +++ /dev/null @@ -1,2 +0,0 @@ -{"type":"info","data":"No lockfile found."} -{"type":"auditSummary","data":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":0,"critical":0},"dependencies":0,"devDependencies":0,"optionalDependencies":0,"totalDependencies":0}} diff --git a/unittests/scans/nowsecure/nowsecure_zero_vuln.json b/unittests/scans/nowsecure/nowsecure_zero_vuln.json new file mode 100644 index 00000000000..a9a50f30107 --- /dev/null +++ b/unittests/scans/nowsecure/nowsecure_zero_vuln.json @@ -0,0 +1,1758 @@ +{ + "data": { + "auto": { + "assessment": { + "ref": "13371337-1337-1337-1337-133713371337", + "applicationRef": "73317331-7331-7331-7331-733173317331", + "platformType": "android", + "packageKey": "com.org.appname", + "packageVersion": "1.0.0", + "taskId": "1231231231231", + "title": "AppName", + "iconURL": "https://api.nowsecure.com/icon/hjfkjz9mxb3bxy3zi1ohraj60oqtpbw63wnvgon8l1ytt49dqwickoczrzopvkvb", + "isAppstoreDownload": false, + "createdAt": "2025-06-20T06:47:15.551Z", + "createdBy": { + "ref": "123123aa-129a-1223-ba11-129c91234asf", + "email": "user@email.com", + "name": "John Doe", + "__typename": "UserSummary" + }, + "buildRef": "123123aa-123a-1a31-123a-1231aa112311", + "buildVersion": "010000", + "upload": { + "ref": "1231acc1-123a-129f-19af-0aa123018391", + "createdAt": "2025-06-20T06:45:16.788Z", + "digest": "25tnhu7gc0u70lw9jnc120rilyz2z1blfnhssinqsgnvpjtvafj0x82ddfclyzri", + "__typename": "AutoUpload" + }, + "analysisConfigLevel": "BASELINE", + "type": "baseline", + "analysisJobType": "FULL", + "staticScore": null, + "score": 100, + "favorite": false, + "assessmentError": null, + "isDebugMode": false, + "hasPreviousAssessmentForComparison": false, + "policy": { + "ref": "1a11aa11-1111-1111-a111-11111aaa1111", + "name": "NowSecure Default Policy", + "createdBy": null, + "createdAt": "2022-07-06T11:04:26.575Z", + "updatedAt": "2025-08-20T16:25:34.128Z", + "archivedAt": null, + "targetType": "ORGANIZATION", + "isDefault": true, + "isNSManaged": true, + "latestVersion": { + "ref": "1111a11a-11aa-1aa1-1a1a-111a11111aa1", + "version": 60, + "trackedVersion": null, + "trackedVersionRef": null, + "__typename": "PolicyVersion" + }, + "targets": [ + { + "ref": "a1a111aa-111a-11aa-111a-11a111a1a1a1", + "type": "ORGANIZATION", + "__typename": "PolicyTarget" + } + ], + "enabled": true, + "trackedPolicy": null, + "__typename": "Policy" + }, + "policyVersion": { + "ref": "a11aa111-1a11-1111-1a1a-11aaa1a111a1", + "policyRef": "1a11aa11-1111-1111-a111-11111aaa1111", + "version": 56, + "policyCategories": [ + { + "policyCategory": 1, + "label": "Needs Remediation", + "description": "NowSecure suggests remediation", + "color": "#CA1108", + "__typename": "PolicyCategory" + }, + { + "policyCategory": 2, + "label": "Review Required", + "description": "NowSecure suggests security review to determine risk", + "color": "#FBA255", + "__typename": "PolicyCategory" + }, + { + "policyCategory": 3, + "label": "Informational", + "description": "NowSecure suggests general review for audit and information", + "color": "#0099ff", + "__typename": "PolicyCategory" + } + ], + "__typename": "PolicyVersion" + }, + "analysis": { + "isAuthenticated": null, + "isCancelled": false, + "isComplete": true, + "isRunning": false, + "status": "completed", + "mappedStatus": "completed", + "errorCode": null, + "error": null, + "artifacts": [ + ], + "screenshots": [ + ], + "task": { + "static": { + "id": "1231231231231.static", + "status": "completed", + "modifiedAt": "2025-06-20T07:18:45.377Z", + "isRunning": false, + "isComplete": true, + "__typename": "AnalysisJob" + }, + "dynamic": { + "id": "1231231231231.dynamic", + "status": "completed", + "modifiedAt": "2025-06-20T07:18:36.233Z", + "isRunning": false, + "isComplete": true, + "__typename": "AnalysisJob" + }, + "__typename": "AnalysisTask" + }, + "__typename": "AutoAssessmentAnalysis" + }, + "build": { + "ref": "123123aa-123a-1a31-123a-1231aa112311", + "digest": "25tnhu7gc0u70lw9jnc120rilyz2z1blfnhssinqsgnvpjtvafj0x82ddfclyzri", + "version": "1.0.0", + "__typename": "AutoBuild" + }, + "group": { + "ref": "a111aaaa-aa11-11aa-1a11-11a111aa1111", + "__typename": "AutoGroup" + }, + "__typename": "AutoAssessment", + "report": { + "createdAt": "2025-06-20T06:47:15.551Z", + "findings": [ + ], + "__typename": "AssessmentReport" + }, + "baseReport": { + "findings": [ + { + "checkId": "apk_insecure_network_config", + "affected": false, + "cvss": 7.5, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_webview_access", + "affected": false, + "cvss": 7.5, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "openssl_cve_2023_0286", + "affected": false, + "cvss": 7.4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "on_received_ssl_error_proceed", + "affected": false, + "cvss": 5.9, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "keysize_check", + "affected": false, + "cvss": 5.9, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "libcurl", + "affected": false, + "cvss": 5.7, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_custom", + "affected": false, + "cvss": 4.4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "unprotected_context_registered_broadcast_receivers", + "affected": false, + "cvss": 4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "unprotected_manifest_broadcast_receivers", + "affected": false, + "cvss": 4, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "libraries_ssp", + "affected": false, + "cvss": 1.6, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_hashing_algorithms", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_deeplinks", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "vulnerable_libraries", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "hardcoded_passwords", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_strandhogg", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_insecure_prng", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_network_config_exceptions", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "android_ssl_vuln", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_intent_redirection", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_hardcoded_secrets", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_device_or_other_ids_collected", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "ai_use_on_device", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "api_hsts", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_textfield_autocorrect", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_certificate_pinning", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_flow", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "zip_file_in_transit_check_https", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_firebase_mfa_not_used", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "kotlin_debug_lib", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_insecure_constants", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "android_debuggable_webviews", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "hardcoded_api_keys", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "javascript_interface_check", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_dangerous_permissions", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "url_listing", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_crypto_keys", + "affected": null, + "cvss": null, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "sms_communications", + "affected": null, + "cvss": null, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "unsigned_jwt", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "sdcard_file_list", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_sqlcipher", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_application_servers", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_padding_oracle", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_iv_hardcoded", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "sql_injection", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "path_traversal", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "serialized_objects", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "arbitrary_code_execution_observed", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "android_static_iv", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "apk_uses_vpn_permission", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "obfuscation_check", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "master_key_check", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "fragment_injection", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "secure_random_check", + "affected": null, + "cvss": 0, + "findingStatus": "inconclusive", + "__typename": "Finding" + }, + { + "checkId": "api_discovery", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_info", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "automation_info", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "behavioral_events", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_connection_domains", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_ivs", + "affected": false, + "cvss": null, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_tracking_domains", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_sensitive_data_pii", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "ai_libraries", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_build_info", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_nsc", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "get_app_files", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "app_sbom", + "affected": false, + "cvss": null, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "snoop_network_hosts", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_sqlite", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "all_android_components", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_permissions", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "get_reflection_code", + "affected": false, + "cvss": 0, + "findingStatus": "detected", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_device_or_other_ids_shared", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_location_collected", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_location_shared", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_personal_info_collected", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_data_safety_personal_info_shared", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "api_authentication", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "api_cors", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "cookie_without_httponly_flag", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "cookie_without_secure_flag", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_insufficient_rounds", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "runs_root_command", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "runs_root_command_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_iv_reuse", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_encryption_modes", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_iv_null", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_weak_crypto_encryption_algorithms", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_root_detection_rasp", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "key_reuse", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_custom", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_logcat_data_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "certificate_validation", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "hostname_verification", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "uses_http", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "zip_file_in_transit_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_cert_validation", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_custom", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "zip_file_in_transit_check_broken_ssl", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sensitive_data_http_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "writable_executable_files_private_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "writable_executable_files_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "world_readable_files_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_sensitive_data_implicit_intents", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "ai_api_keys", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "world_writable_files_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "remote_code_execution", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "arbitrary_code_execution_probable", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_leaked_data_sdcard", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_bluetooth_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_build_fingerprint", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_custom", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_dns1", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_dns2", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_email", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_firstname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_name", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_gpslatitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_gpslongitude", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_lastname", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_localwifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_password", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_phonenumber", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_memdump_data_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_surrounding_wifi_network_bssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_surrounding_wifi_network_ssid", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_surrounding_wifimac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_android_id", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_serial", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_imei", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_wifi_ip", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_username", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_wifi_mac", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "leaked_data_in_files_zipcode", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_biometric_key_invalidation_disabled", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_janus_vuln", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "openssl_cve_2014_0224", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "openssl_cve_2014_0160", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "debug_flag_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_minimum_sdk", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_debug_symbols", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "joda_cve", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_ftp_libs", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_target_sdk_min", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "allow_backup_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "get_native_methods", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "sqlcipher_key_leakage_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_blocker_apptentive", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "exported_components", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "android_janus_warn", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_libraries_aslr", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "okhttp", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "libpng_cve", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "play_services_basement", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "potential_sqlcipher_key_leakage_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_blocker_segment", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_in_app_updates", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "use_of_deprecated_xamarin", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "certificate_validity_check", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + }, + { + "checkId": "apk_vpn_always_on_not_available", + "affected": false, + "cvss": 0, + "findingStatus": "pass", + "__typename": "Finding" + } + ], + "__typename": "AssessmentReport" + } + }, + "__typename": "AutoQuery" + } + } +} diff --git a/unittests/tools/test_nowsecure_parser.py b/unittests/tools/test_nowsecure_parser.py index 17aaa2a5b69..8f0259a9bf0 100644 --- a/unittests/tools/test_nowsecure_parser.py +++ b/unittests/tools/test_nowsecure_parser.py @@ -6,14 +6,14 @@ class TestNowSecureParser(TestCase): def test_nowsecure_parser_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/nowsecure/nowsecure_zero_vul.json") + testfile = open("unittests/scans/nowsecure/nowsecure_zero_vuln.json") parser = NowSecureParser() findings = parser.get_findings(testfile, Test()) testfile.close() self.assertEqual(0, len(findings)) - def test_nowsecure_parser_with_one_criticle_vuln_has_one_findings(self): - testfile = open("unittests/scans/nowsecure/nowsecure_one_vul.json") + def test_nowsecure_parser_with_one_vuln_has_one_findings(self): + testfile = open("unittests/scans/nowsecure/nowsecure_one_vuln.json") parser = NowSecureParser() findings = parser.get_findings(testfile, Test()) testfile.close() @@ -21,29 +21,44 @@ def test_nowsecure_parser_with_one_criticle_vuln_has_one_findings(self): for endpoint in finding.unsaved_endpoints: endpoint.clean() self.assertEqual(1, len(findings)) - self.assertEqual("handlebars", findings[0].component_name) - self.assertEqual("4.5.2", findings[0].component_version) + self.assertEqual("App Configuration Allows Insecure Network Connections", findings[0].title) + self.assertEqual("The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.", findings[0].description) + self.assertEqual("high".capitalize(), findings[0].severity) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", findings[0].cvssv3) + self.assertEqual(7.5, findings[0].cvssv3_score) + self.assertEqual("The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).", findings[0].mitigation) + self.assertEqual("Allowing cleartext network connections allows attackers to intercept, inspect or manipulate data transmitted between the app and external servers, compromising the integrity and confidentiality of user information. This vulnerability can have serious business implications, particularly in the event of a data breach, including loss of customer trust, potential legal liabilities and financial penalties.", findings[0].impact) + def test_nowsecure_parser_with_many_vuln_has_many_findings(self): - testfile = open("unittests/scans/nowsecure/nowsecure_many_vul.json") + testfile = open("unittests/scans/nowsecure/nowsecure_many_vuln.json") parser = NowSecureParser() findings = parser.get_findings(testfile, Test()) testfile.close() for finding in findings: for endpoint in finding.unsaved_endpoints: endpoint.clean() - self.assertEqual(3, len(findings)) + self.assertEqual(5, len(findings)) + self.assertEqual("App Configuration Allows Insecure Network Connections", findings[0].title) + self.assertEqual("WebViews Allowing Access to Local Files", findings[1].title) + self.assertEqual("The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.", findings[0].description) + self.assertEqual("high".capitalize(), findings[0].severity) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", findings[0].cvssv3) + self.assertEqual(7.5, findings[0].cvssv3_score) + self.assertEqual(5.9, findings[4].cvssv3_score) + self.assertEqual("The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).", findings[0].mitigation) + self.assertEqual("Allowing cleartext network connections allows attackers to intercept, inspect or manipulate data transmitted between the app and external servers, compromising the integrity and confidentiality of user information. This vulnerability can have serious business implications, particularly in the event of a data breach, including loss of customer trust, potential legal liabilities and financial penalties.", findings[0].impact) - def test_nowsecure_parser_empty_with_error(self): - with self.assertRaises(ValueError) as context: - testfile = open("unittests/scans/nowsecure/empty_with_error.json") - parser = NowSecureParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertTrue( - "NowSecure report contains errors:" in str(context.exception) - ) - self.assertTrue("ECONNREFUSED" in str(context.exception)) + # def test_nowsecure_parser_empty_with_error(self): + # with self.assertRaises(ValueError) as context: + # testfile = open("unittests/scans/nowsecure/empty_with_error.json") + # parser = NowSecureParser() + # findings = parser.get_findings(testfile, Test()) + # testfile.close() + # for finding in findings: + # for endpoint in finding.unsaved_endpoints: + # endpoint.clean() + # self.assertTrue( + # "NowSecure report contains errors:" in str(context.exception) + # ) + # self.assertTrue("ECONNREFUSED" in str(context.exception)) From 6628ac57d069aef268203e89434c3ae451f080be Mon Sep 17 00:00:00 2001 From: Marcos Carro Fernandez Date: Mon, 1 Sep 2025 15:06:39 +0200 Subject: [PATCH 3/8] Added readme for nowsecure parser --- .../parsers/file/nowsecure.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 docs/content/en/connecting_your_tools/parsers/file/nowsecure.md diff --git a/docs/content/en/connecting_your_tools/parsers/file/nowsecure.md b/docs/content/en/connecting_your_tools/parsers/file/nowsecure.md new file mode 100644 index 00000000000..08eb878a370 --- /dev/null +++ b/docs/content/en/connecting_your_tools/parsers/file/nowsecure.md @@ -0,0 +1,25 @@ +--- +title: "NowSecure" +toc_hide: true +--- +This parser imports the Now Secure app analysis resutls using `json` output. + +### Sample analysis Data +Sample NowSecure result files can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/nowsecure). + +### Using your own data + +```sh +# https://support.nowsecure.com/hc/en-us/articles/7499657262093-Creating-a-NowSecure-Platform-API-Bearer-Token +API_TOKEN="" +# Can be obteained from the Webui +APP_REF="" +# Sample CURL request (beware of the pipe to jq!) +curl 'https://api.nowsecure.com/graphql' -H 'Accept-Language: en-US,en;q=0.9' -H 'Connection: keep-alive' -H 'Origin: https://app.nowsecure.com' -H 'Referer: https://app.nowsecure.com/' -H 'Sec-Fetch-Dest: empty' -H 'Sec-Fetch-Mode: cors' -H 'Sec-Fetch-Site: same-site' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36' -H 'accept: */*' -H "authorization: Bearer ${API_TOKEN}" -H 'client-source: platform' -H 'content-type: application/json' -H 'sec-ch-ua: "Not;A=Brand";v="99", "Google Chrome";v="139", "Chromium";v="139"' -H 'sec-ch-ua-mobile: ?0' -H 'sec-ch-ua-platform: "macOS"' --data-raw "{\"operationName\":\"getAssessment\",\"variables\":{\"canViewPolicies\":true,\"ref\":\"${app_ref}\",\"policyVersionRef\":null,\"catalog\":null},\"query\":\"query getAssessment(\$ref: UUID\u0021, \$canViewPolicies: Boolean = false, \$policyVersionRef: UUID, \$catalog: ComplianceReportCatalog) {\\n auto {\\n assessment(ref: \$ref, policyVersionRef: \$policyVersionRef) {\\n ...assessment\\n __typename\\n }\\n __typename\\n }\\n}\\n\\nfragment assessment on AutoAssessment {\\n ...assessmentWithoutReport\\n report {\\n ...report\\n __typename\\n }\\n baseReport {\\n findings(hidden: true, indeterminate: true) {\\n checkId\\n affected\\n cvss\\n findingStatus\\n __typename\\n }\\n __typename\\n }\\n __typename\\n}\\n\\nfragment assessmentWithoutReport on AutoAssessment {\\n ref\\n applicationRef\\n platformType\\n packageKey\\n packageVersion\\n taskId\\n title\\n iconURL\\n isAppstoreDownload\\n createdAt\\n createdBy {\\n ref\\n email\\n name\\n __typename\\n }\\n buildRef\\n buildVersion\\n upload {\\n ref\\n createdAt\\n digest\\n __typename\\n }\\n analysisConfigLevel\\n type\\n analysisJobType\\n staticScore\\n score\\n favorite\\n assessmentError {\\n code\\n title\\n description\\n options\\n __typename\\n }\\n isDebugMode\\n hasPreviousAssessmentForComparison\\n policy @include(if: \$canViewPolicies) {\\n ...litePolicy\\n __typename\\n }\\n policyVersion @include(if: \$canViewPolicies) {\\n ref\\n policyRef\\n version\\n policyCategories {\\n policyCategory\\n label\\n description\\n color\\n __typename\\n }\\n __typename\\n }\\n analysis {\\n isAuthenticated\\n isCancelled\\n isComplete\\n isRunning\\n status\\n mappedStatus\\n errorCode\\n error {\\n code\\n message\\n __typename\\n }\\n artifacts(artifactType: HAR) {\\n assessmentRef\\n ref\\n artifactType\\n tags\\n displayName\\n byteSize\\n filename\\n contentType\\n url\\n __typename\\n }\\n screenshots {\\n ref\\n url\\n analysisPass\\n __typename\\n }\\n task {\\n static {\\n ...analysisJob\\n __typename\\n }\\n dynamic {\\n ...analysisJob\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n build {\\n ref\\n digest\\n version\\n __typename\\n }\\n group {\\n ref\\n __typename\\n }\\n __typename\\n}\\n\\nfragment analysisJob on AnalysisJob {\\n id\\n status\\n modifiedAt\\n isRunning\\n isComplete\\n __typename\\n}\\n\\nfragment litePolicy on Policy {\\n ref\\n name\\n createdBy\\n createdAt\\n updatedAt\\n archivedAt\\n targetType\\n isDefault\\n isNSManaged\\n latestVersion {\\n ref\\n version\\n trackedVersion\\n trackedVersionRef\\n __typename\\n }\\n targets {\\n ref\\n type\\n __typename\\n }\\n enabled\\n trackedPolicy {\\n ref\\n name\\n latestVersion {\\n ref\\n version\\n __typename\\n }\\n __typename\\n }\\n __typename\\n}\\n\\nfragment report on AssessmentReport {\\n createdAt\\n findings(hidden: true, indeterminate: true) {\\n ...reportFinding\\n __typename\\n }\\n __typename\\n}\\n\\nfragment reportFinding on Finding {\\n affected\\n checkId\\n uniqueVulnerabilityId\\n check {\\n ...findingCheck\\n __typename\\n }\\n userChanges {\\n date\\n user {\\n name\\n __typename\\n }\\n __typename\\n }\\n cvss\\n cvssVector\\n findingStatus\\n decision\\n decisionInfo {\\n note\\n reason\\n wasInherited\\n __typename\\n }\\n evidenceDecision\\n hidden\\n impactType\\n severity\\n note\\n adjustments\\n shortRemediation\\n title\\n hasContext\\n hasCodeLocations\\n canHaveActionableEvidence\\n hasActionedEvidence\\n policyCategory @include(if: \$canViewPolicies) {\\n policyCategory\\n color\\n label\\n __typename\\n }\\n policyFindingOverrides {\\n checkId\\n cvss\\n cvssVector\\n hidden\\n impactType\\n __typename\\n }\\n complianceReportRelations(catalog: \$catalog) {\\n catalog\\n groupId\\n controlId\\n version\\n __typename\\n }\\n __typename\\n}\\n\\nfragment findingCheck on FindingCheck {\\n id\\n analysisType\\n title\\n description\\n shortDescription\\n platformType\\n category\\n categories\\n legacyFindingKey\\n isNew\\n deprecated\\n context {\\n view\\n title\\n fields {\\n key\\n format\\n title\\n description\\n __typename\\n }\\n children {\\n view\\n title\\n fields {\\n key\\n format\\n title\\n description\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n issue {\\n cvss\\n cvssVector\\n title\\n description\\n recommendation\\n passingContent\\n category\\n severity\\n warn\\n impactSummary\\n regulations {\\n type\\n label\\n links {\\n title\\n url\\n __typename\\n }\\n __typename\\n }\\n stepsToReproduce\\n codeSamples {\\n platform\\n syntax\\n caption\\n block\\n __typename\\n }\\n guidanceLinks {\\n platform\\n caption\\n url\\n __typename\\n }\\n __typename\\n }\\n compliance {\\n regulation {\\n description\\n __typename\\n }\\n notes {\\n description\\n __typename\\n }\\n activity {\\n tss {\\n description\\n __typename\\n }\\n guidance {\\n description\\n __typename\\n }\\n tests {\\n description\\n __typename\\n }\\n __typename\\n }\\n nowSecureGuidance {\\n description\\n __typename\\n }\\n __typename\\n }\\n __typename\\n}\\n\"}" | jq +``` + +### Default Deduplication Hashcode Fields +By default, DefectDojo identifies duplicate Findings using these [hashcode fields](https://docs.defectdojo.com/en/working_with_findings/finding_deduplication/about_deduplication/): + +- title +- description \ No newline at end of file From a73fe012081c27d854345d738f36ab82c69f545a Mon Sep 17 00:00:00 2001 From: Marcos Carro Fernandez Date: Mon, 1 Sep 2025 15:24:17 +0200 Subject: [PATCH 4/8] deleted default lines that were commented out --- dojo/tools/nowsecure/parser.py | 102 ----------------------- unittests/tools/test_nowsecure_parser.py | 14 ---- 2 files changed, 116 deletions(-) diff --git a/dojo/tools/nowsecure/parser.py b/dojo/tools/nowsecure/parser.py index e4b5c6f282e..a15dbfb6a2c 100644 --- a/dojo/tools/nowsecure/parser.py +++ b/dojo/tools/nowsecure/parser.py @@ -1,105 +1,3 @@ -# import hashlib -# import json -# from urllib.parse import urlparse -# from dojo.models import Endpoint, Finding - - -# class NowSecureParser(object): -# """ -# testing apps that touch your enterprise, preventing data leakage or unauthorized access. -# """ - -# def get_scan_types(self): -# return ["NowSecure Scan"] - -# def get_label_for_scan_types(self, scan_type): -# return "NowSecure Scan" - -# def get_description_for_scan_types(self, scan_type): -# return "NowSecure report file can be imported in JSON format (option --json)." - -# def get_findings(self, file, test): -# data = json.load(file) - -# dupes = dict() -# for content in tree: -# node = tree[content] -# if not node['pass']: -# title = node['name'] -# description = "**Score Description** : " + node['score_description'] + "\n\n" + \ -# "**Result** : " + node['result'] + "\n\n" + \ -# "**expectation** : " + node['expectation'] + "\n" -# severity = self.get_severity(int(node['score_modifier'])) -# output = node['output'] -# try: -# url = output['destination'] -# parsedUrl = urlparse(url) -# protocol = parsedUrl.scheme -# query = parsedUrl.query -# fragment = parsedUrl.fragment -# path = parsedUrl.path -# port = "" -# try: -# host, port = parsedUrl.netloc.split(':') -# except: -# host = parsedUrl.netloc -# except: -# url = None - -# finding = Finding( -# title=title, -# test=test, -# description=description, -# severity=severity, - -# static_finding=True, -# dynamic_finding=False, -# ) - -# # some attribute are optional -# if 'mitigationFromTheTool' in node: -# finding.mitigation = node['mitigationFromTheTool'] - -# # take a look at all the attributes possible in the documentation -# # some are very usefull like -# # - date (DATE / date when the finding was detected) -# # - component_name (STRING / if the finding is liked to an external component ex: 'log4j') -# # - component_version (STRING / if the finding is liked to an external component ex: '1.2.13') -# # - file_path (STRING / if the finding is liked to a specfic file ex: 'src/foo.c') -# # - line (INTEGER / if the finding is liked to an specific file ex: 23) - -# # manage endpoint -# finding.unsaved_endpoints = list() -# if url is not None: -# finding.unsaved_endpoints.append(Endpoint( -# host=host, port=port, -# path=path, -# protocol=protocol, -# query=query, fragment=fragment)) - -# # internal de-duplication -# dupe_key = hashlib.sha256(str(description + title).encode('utf-8')).hexdigest() -# if dupe_key in dupes: -# find = dupes[dupe_key] -# if finding.description: -# find.description += "\n" + finding.description -# find.unsaved_endpoints.extend(finding.unsaved_endpoints) -# dupes[dupe_key] = find -# else: -# dupes[dupe_key] = finding - -# return list(dupes.values()) - -# def convert_severity(self, num_severity): -# """Convert severity value""" -# if num_severity >= -10: -# return "Low" -# elif -11 >= num_severity > -26: -# return "Medium" -# elif num_severity <= -26: -# return "High" -# else: -# return "Info" import hashlib import json from urllib.parse import urlparse diff --git a/unittests/tools/test_nowsecure_parser.py b/unittests/tools/test_nowsecure_parser.py index 8f0259a9bf0..3e145cbff56 100644 --- a/unittests/tools/test_nowsecure_parser.py +++ b/unittests/tools/test_nowsecure_parser.py @@ -48,17 +48,3 @@ def test_nowsecure_parser_with_many_vuln_has_many_findings(self): self.assertEqual(5.9, findings[4].cvssv3_score) self.assertEqual("The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).", findings[0].mitigation) self.assertEqual("Allowing cleartext network connections allows attackers to intercept, inspect or manipulate data transmitted between the app and external servers, compromising the integrity and confidentiality of user information. This vulnerability can have serious business implications, particularly in the event of a data breach, including loss of customer trust, potential legal liabilities and financial penalties.", findings[0].impact) - - # def test_nowsecure_parser_empty_with_error(self): - # with self.assertRaises(ValueError) as context: - # testfile = open("unittests/scans/nowsecure/empty_with_error.json") - # parser = NowSecureParser() - # findings = parser.get_findings(testfile, Test()) - # testfile.close() - # for finding in findings: - # for endpoint in finding.unsaved_endpoints: - # endpoint.clean() - # self.assertTrue( - # "NowSecure report contains errors:" in str(context.exception) - # ) - # self.assertTrue("ECONNREFUSED" in str(context.exception)) From c78cd07ef473ee26b862652d5aaf66396a43b84f Mon Sep 17 00:00:00 2001 From: Marcos Carro Fernandez Date: Mon, 1 Sep 2025 16:34:00 +0200 Subject: [PATCH 5/8] Added fix_available field and docummented behavior --- .../en/connecting_your_tools/parsers/file/nowsecure.md | 3 +++ dojo/tools/nowsecure/parser.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/docs/content/en/connecting_your_tools/parsers/file/nowsecure.md b/docs/content/en/connecting_your_tools/parsers/file/nowsecure.md index 08eb878a370..0f6146a45ba 100644 --- a/docs/content/en/connecting_your_tools/parsers/file/nowsecure.md +++ b/docs/content/en/connecting_your_tools/parsers/file/nowsecure.md @@ -17,6 +17,9 @@ APP_REF="" # Sample CURL request (beware of the pipe to jq!) curl 'https://api.nowsecure.com/graphql' -H 'Accept-Language: en-US,en;q=0.9' -H 'Connection: keep-alive' -H 'Origin: https://app.nowsecure.com' -H 'Referer: https://app.nowsecure.com/' -H 'Sec-Fetch-Dest: empty' -H 'Sec-Fetch-Mode: cors' -H 'Sec-Fetch-Site: same-site' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36' -H 'accept: */*' -H "authorization: Bearer ${API_TOKEN}" -H 'client-source: platform' -H 'content-type: application/json' -H 'sec-ch-ua: "Not;A=Brand";v="99", "Google Chrome";v="139", "Chromium";v="139"' -H 'sec-ch-ua-mobile: ?0' -H 'sec-ch-ua-platform: "macOS"' --data-raw "{\"operationName\":\"getAssessment\",\"variables\":{\"canViewPolicies\":true,\"ref\":\"${app_ref}\",\"policyVersionRef\":null,\"catalog\":null},\"query\":\"query getAssessment(\$ref: UUID\u0021, \$canViewPolicies: Boolean = false, \$policyVersionRef: UUID, \$catalog: ComplianceReportCatalog) {\\n auto {\\n assessment(ref: \$ref, policyVersionRef: \$policyVersionRef) {\\n ...assessment\\n __typename\\n }\\n __typename\\n }\\n}\\n\\nfragment assessment on AutoAssessment {\\n ...assessmentWithoutReport\\n report {\\n ...report\\n __typename\\n }\\n baseReport {\\n findings(hidden: true, indeterminate: true) {\\n checkId\\n affected\\n cvss\\n findingStatus\\n __typename\\n }\\n __typename\\n }\\n __typename\\n}\\n\\nfragment assessmentWithoutReport on AutoAssessment {\\n ref\\n applicationRef\\n platformType\\n packageKey\\n packageVersion\\n taskId\\n title\\n iconURL\\n isAppstoreDownload\\n createdAt\\n createdBy {\\n ref\\n email\\n name\\n __typename\\n }\\n buildRef\\n buildVersion\\n upload {\\n ref\\n createdAt\\n digest\\n __typename\\n }\\n analysisConfigLevel\\n type\\n analysisJobType\\n staticScore\\n score\\n favorite\\n assessmentError {\\n code\\n title\\n description\\n options\\n __typename\\n }\\n isDebugMode\\n hasPreviousAssessmentForComparison\\n policy @include(if: \$canViewPolicies) {\\n ...litePolicy\\n __typename\\n }\\n policyVersion @include(if: \$canViewPolicies) {\\n ref\\n policyRef\\n version\\n policyCategories {\\n policyCategory\\n label\\n description\\n color\\n __typename\\n }\\n __typename\\n }\\n analysis {\\n isAuthenticated\\n isCancelled\\n isComplete\\n isRunning\\n status\\n mappedStatus\\n errorCode\\n error {\\n code\\n message\\n __typename\\n }\\n artifacts(artifactType: HAR) {\\n assessmentRef\\n ref\\n artifactType\\n tags\\n displayName\\n byteSize\\n filename\\n contentType\\n url\\n __typename\\n }\\n screenshots {\\n ref\\n url\\n analysisPass\\n __typename\\n }\\n task {\\n static {\\n ...analysisJob\\n __typename\\n }\\n dynamic {\\n ...analysisJob\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n build {\\n ref\\n digest\\n version\\n __typename\\n }\\n group {\\n ref\\n __typename\\n }\\n __typename\\n}\\n\\nfragment analysisJob on AnalysisJob {\\n id\\n status\\n modifiedAt\\n isRunning\\n isComplete\\n __typename\\n}\\n\\nfragment litePolicy on Policy {\\n ref\\n name\\n createdBy\\n createdAt\\n updatedAt\\n archivedAt\\n targetType\\n isDefault\\n isNSManaged\\n latestVersion {\\n ref\\n version\\n trackedVersion\\n trackedVersionRef\\n __typename\\n }\\n targets {\\n ref\\n type\\n __typename\\n }\\n enabled\\n trackedPolicy {\\n ref\\n name\\n latestVersion {\\n ref\\n version\\n __typename\\n }\\n __typename\\n }\\n __typename\\n}\\n\\nfragment report on AssessmentReport {\\n createdAt\\n findings(hidden: true, indeterminate: true) {\\n ...reportFinding\\n __typename\\n }\\n __typename\\n}\\n\\nfragment reportFinding on Finding {\\n affected\\n checkId\\n uniqueVulnerabilityId\\n check {\\n ...findingCheck\\n __typename\\n }\\n userChanges {\\n date\\n user {\\n name\\n __typename\\n }\\n __typename\\n }\\n cvss\\n cvssVector\\n findingStatus\\n decision\\n decisionInfo {\\n note\\n reason\\n wasInherited\\n __typename\\n }\\n evidenceDecision\\n hidden\\n impactType\\n severity\\n note\\n adjustments\\n shortRemediation\\n title\\n hasContext\\n hasCodeLocations\\n canHaveActionableEvidence\\n hasActionedEvidence\\n policyCategory @include(if: \$canViewPolicies) {\\n policyCategory\\n color\\n label\\n __typename\\n }\\n policyFindingOverrides {\\n checkId\\n cvss\\n cvssVector\\n hidden\\n impactType\\n __typename\\n }\\n complianceReportRelations(catalog: \$catalog) {\\n catalog\\n groupId\\n controlId\\n version\\n __typename\\n }\\n __typename\\n}\\n\\nfragment findingCheck on FindingCheck {\\n id\\n analysisType\\n title\\n description\\n shortDescription\\n platformType\\n category\\n categories\\n legacyFindingKey\\n isNew\\n deprecated\\n context {\\n view\\n title\\n fields {\\n key\\n format\\n title\\n description\\n __typename\\n }\\n children {\\n view\\n title\\n fields {\\n key\\n format\\n title\\n description\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n issue {\\n cvss\\n cvssVector\\n title\\n description\\n recommendation\\n passingContent\\n category\\n severity\\n warn\\n impactSummary\\n regulations {\\n type\\n label\\n links {\\n title\\n url\\n __typename\\n }\\n __typename\\n }\\n stepsToReproduce\\n codeSamples {\\n platform\\n syntax\\n caption\\n block\\n __typename\\n }\\n guidanceLinks {\\n platform\\n caption\\n url\\n __typename\\n }\\n __typename\\n }\\n compliance {\\n regulation {\\n description\\n __typename\\n }\\n notes {\\n description\\n __typename\\n }\\n activity {\\n tss {\\n description\\n __typename\\n }\\n guidance {\\n description\\n __typename\\n }\\n tests {\\n description\\n __typename\\n }\\n __typename\\n }\\n nowSecureGuidance {\\n description\\n __typename\\n }\\n __typename\\n }\\n __typename\\n}\\n\"}" | jq ``` +### Other considerations + +* `fix_available` will be set to true if the `mitigation` field isn't empty. ### Default Deduplication Hashcode Fields By default, DefectDojo identifies duplicate Findings using these [hashcode fields](https://docs.defectdojo.com/en/working_with_findings/finding_deduplication/about_deduplication/): diff --git a/dojo/tools/nowsecure/parser.py b/dojo/tools/nowsecure/parser.py index a15dbfb6a2c..07db2440c23 100644 --- a/dojo/tools/nowsecure/parser.py +++ b/dojo/tools/nowsecure/parser.py @@ -34,6 +34,10 @@ def get_findings(self, file, test): cvssv3 = content['check']['issue']['cvssVector'] cvssv3_score = content['check']['issue']['cvss'] mitigation = content['check']['issue']['recommendation'] + if len(mitigation) > 0: + fix_available=True + else: + fix_available=False impact = content['check']['issue']['impactSummary'] url = f"https://app.nowsecure.com/app/{data['data']['auto']['assessment']['applicationRef']}/assessment/{data['data']['auto']['assessment']['ref']}?viewObservationsBy=categories&viewFindingsBy=policyCategory#{content['checkId']}" steps_to_reproduce = (content['check']['issue']['stepsToReproduce'] or '''''') @@ -77,6 +81,7 @@ def get_findings(self, file, test): references = references, cwe = cwe, cve = cve, + fix_available = fix_available, static_finding=True, dynamic_finding=False, From 2bfcb22c362234976204c2299ced592f8fd25fff Mon Sep 17 00:00:00 2001 From: Marcos Carro Fernandez Date: Mon, 1 Sep 2025 16:44:56 +0200 Subject: [PATCH 6/8] added fix_available setting to parser --- dojo/tools/nowsecure/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/nowsecure/parser.py b/dojo/tools/nowsecure/parser.py index 07db2440c23..a573aaf4134 100644 --- a/dojo/tools/nowsecure/parser.py +++ b/dojo/tools/nowsecure/parser.py @@ -34,7 +34,7 @@ def get_findings(self, file, test): cvssv3 = content['check']['issue']['cvssVector'] cvssv3_score = content['check']['issue']['cvss'] mitigation = content['check']['issue']['recommendation'] - if len(mitigation) > 0: + if mitigation: fix_available=True else: fix_available=False From f0717b573fdc57d8995663792212c5fba5d46a7e Mon Sep 17 00:00:00 2001 From: Marcos Carro Fernandez Date: Tue, 2 Sep 2025 09:22:53 +0200 Subject: [PATCH 7/8] Added standard DefecDojo CVSS parsing, modified 'for..in..:' structures for resilience and modified unittests accordingly --- dojo/tools/nowsecure/parser.py | 39 +++++++++++++++--------- unittests/tools/test_nowsecure_parser.py | 3 -- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/dojo/tools/nowsecure/parser.py b/dojo/tools/nowsecure/parser.py index a573aaf4134..70de2fca994 100644 --- a/dojo/tools/nowsecure/parser.py +++ b/dojo/tools/nowsecure/parser.py @@ -2,8 +2,10 @@ import json from urllib.parse import urlparse from dojo.models import Endpoint, Finding +from dojo.utils import parse_cvss_data import re + class NowSecureParser(object): """ Importing findings from NowSecure app analysis. @@ -22,41 +24,50 @@ def get_findings(self, file, test): data = json.load(file) dupes = dict() - for content in data['data']['auto']['assessment']['report']['findings']: + for content in data.get('data', {}).get('auto', {}).get('assessment', {}).get('report', {}).get('findings', []): if content['affected']: if content['check']['issue']: + # If the issue exist, it always has a title title = content['check']['issue']['title'] - for regulation in content['check']['issue']['regulations']: + for regulation in content.get('check',{}).get('issue',{}).get('regulations',[]): if regulation['type'] == "cwe": cwe = regulation['links'][0]['title'] - description = content['check']['issue']['description'] - severity = content['check']['issue']['severity'].capitalize() - cvssv3 = content['check']['issue']['cvssVector'] - cvssv3_score = content['check']['issue']['cvss'] - mitigation = content['check']['issue']['recommendation'] - if mitigation: + description = content['check']['issue']['description'] or '''''' + # https://docs.defectdojo.com/en/open_source/contributing/how-to-write-a-parser/#parsing-of-cvss-vectors + if content['check']['issue']['cvssVector']: + cvss_vector = content['check']['issue']['cvssVector'] + cvss_data = parse_cvss_data(cvss_vector) + if cvss_data: + severity = cvss_data["severity"] + cvssv3 = cvss_data["cvssv3"] + cvssv4 = cvss_data["cvssv4"] + # we don't set any score fields as those will be overwritten by Defect Dojo + if content['check']['issue']['recommendation']: + mitigation = content['check']['issue']['recommendation'] fix_available=True else: fix_available=False - impact = content['check']['issue']['impactSummary'] - url = f"https://app.nowsecure.com/app/{data['data']['auto']['assessment']['applicationRef']}/assessment/{data['data']['auto']['assessment']['ref']}?viewObservationsBy=categories&viewFindingsBy=policyCategory#{content['checkId']}" + + impact = content['check']['issue']['impactSummary'] or '''''' + if data['data']['auto']['assessment']['applicationRef'] and data['data']['auto']['assessment']['ref'] and content['checkId']: + url = f"https://app.nowsecure.com/app/{data['data']['auto']['assessment']['applicationRef']}/assessment/{data['data']['auto']['assessment']['ref']}?viewObservationsBy=categories&viewFindingsBy=policyCategory#{content['checkId']}" steps_to_reproduce = (content['check']['issue']['stepsToReproduce'] or '''''') if content['check']['issue']['codeSamples']: code_samples = '''''' - for code_sample in content['check']['issue']['codeSamples']: + for code_sample in content.get('check',{}).get('issue',{}).get('codeSamples',[]): code_samples += f'''**{code_sample['platform']}**: {code_sample['caption']}\n```{code_sample['syntax']}\n{code_sample['block']}\n```\n''' if code_samples: steps_to_reproduce += code_samples references = '''''' if content['check']['issue']['guidanceLinks']: references+="### Guidance Links\n" - for reference in content['check']['issue']['guidanceLinks']: + for reference in content.get('check',{}).get('issue',{}).get('guidanceLinks',[]): references+=f'''* [{reference['caption']}]({reference['url']})\n''' cwe = None if content['check']['issue']['regulations']: references+="### Regulations\n" - for regulation in content['check']['issue']['regulations']: + for regulation in content.get('check',{}).get('issue',{}).get('regulations',[]): if regulation['type'] == 'cwe': cwe = regulation['links'][0]['title'] for link in regulation['links']: @@ -73,7 +84,7 @@ def get_findings(self, file, test): description=description, severity=severity, cvssv3 = cvssv3, - cvssv3_score = cvssv3_score, + cvssv4 = cvssv4, mitigation = mitigation, url = url, steps_to_reproduce = steps_to_reproduce, diff --git a/unittests/tools/test_nowsecure_parser.py b/unittests/tools/test_nowsecure_parser.py index 3e145cbff56..cf2ba3222ee 100644 --- a/unittests/tools/test_nowsecure_parser.py +++ b/unittests/tools/test_nowsecure_parser.py @@ -25,7 +25,6 @@ def test_nowsecure_parser_with_one_vuln_has_one_findings(self): self.assertEqual("The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.", findings[0].description) self.assertEqual("high".capitalize(), findings[0].severity) self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", findings[0].cvssv3) - self.assertEqual(7.5, findings[0].cvssv3_score) self.assertEqual("The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).", findings[0].mitigation) self.assertEqual("Allowing cleartext network connections allows attackers to intercept, inspect or manipulate data transmitted between the app and external servers, compromising the integrity and confidentiality of user information. This vulnerability can have serious business implications, particularly in the event of a data breach, including loss of customer trust, potential legal liabilities and financial penalties.", findings[0].impact) @@ -44,7 +43,5 @@ def test_nowsecure_parser_with_many_vuln_has_many_findings(self): self.assertEqual("The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.", findings[0].description) self.assertEqual("high".capitalize(), findings[0].severity) self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", findings[0].cvssv3) - self.assertEqual(7.5, findings[0].cvssv3_score) - self.assertEqual(5.9, findings[4].cvssv3_score) self.assertEqual("The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).", findings[0].mitigation) self.assertEqual("Allowing cleartext network connections allows attackers to intercept, inspect or manipulate data transmitted between the app and external servers, compromising the integrity and confidentiality of user information. This vulnerability can have serious business implications, particularly in the event of a data breach, including loss of customer trust, potential legal liabilities and financial penalties.", findings[0].impact) From 35338b31d68292c7ed904875cccbf1a58b388ef3 Mon Sep 17 00:00:00 2001 From: Marcos Carro Fernandez Date: Thu, 4 Sep 2025 23:00:17 +0200 Subject: [PATCH 8/8] Modified parser for adequately parsing CVSS and modified JSON access in favour of more resilient methods --- dojo/tools/nowsecure/parser.py | 60 ++++++++++++------------ unittests/tools/test_nowsecure_parser.py | 12 ++--- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/dojo/tools/nowsecure/parser.py b/dojo/tools/nowsecure/parser.py index 70de2fca994..59cb6e881f4 100644 --- a/dojo/tools/nowsecure/parser.py +++ b/dojo/tools/nowsecure/parser.py @@ -22,56 +22,58 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): data = json.load(file) - dupes = dict() for content in data.get('data', {}).get('auto', {}).get('assessment', {}).get('report', {}).get('findings', []): - if content['affected']: - if content['check']['issue']: + if content.get('affected',[]): + if content.get('check',{}).get('issue',[]): # If the issue exist, it always has a title - title = content['check']['issue']['title'] + title = content.get('check',{}).get('issue',{}).get('title',[]) for regulation in content.get('check',{}).get('issue',{}).get('regulations',[]): - if regulation['type'] == "cwe": - cwe = regulation['links'][0]['title'] - description = content['check']['issue']['description'] or '''''' + if regulation.get('type',[]) == "cwe": + cwe = regulation.get('links',[])[0].get('title',[]) + if content.get('check',{}).get('issue',{}).get('description',[]): + description = content.get('check',{}).get('issue',{}).get('description',[]) + else: + description = '''''' # https://docs.defectdojo.com/en/open_source/contributing/how-to-write-a-parser/#parsing-of-cvss-vectors - if content['check']['issue']['cvssVector']: - cvss_vector = content['check']['issue']['cvssVector'] + if content.get('check',{}).get('issue',{}).get('cvssVector',[]): + cvss_vector = content.get('check',{}).get('issue',{}).get('cvssVector',[]) cvss_data = parse_cvss_data(cvss_vector) if cvss_data: - severity = cvss_data["severity"] - cvssv3 = cvss_data["cvssv3"] - cvssv4 = cvss_data["cvssv4"] + severity = cvss_data.get('severity',[]) + cvssv3 = cvss_data.get('cvssv3',[]) + cvssv4 = cvss_data.get('cvssv4',[]) # we don't set any score fields as those will be overwritten by Defect Dojo - if content['check']['issue']['recommendation']: - mitigation = content['check']['issue']['recommendation'] + if content.get('check',{}).get('issue',{}).get('recommendation',[]): + mitigation = content.get('check',{}).get('issue',{}).get('recommendation',[]) fix_available=True else: fix_available=False - impact = content['check']['issue']['impactSummary'] or '''''' - if data['data']['auto']['assessment']['applicationRef'] and data['data']['auto']['assessment']['ref'] and content['checkId']: - url = f"https://app.nowsecure.com/app/{data['data']['auto']['assessment']['applicationRef']}/assessment/{data['data']['auto']['assessment']['ref']}?viewObservationsBy=categories&viewFindingsBy=policyCategory#{content['checkId']}" - steps_to_reproduce = (content['check']['issue']['stepsToReproduce'] or '''''') - if content['check']['issue']['codeSamples']: + impact = content.get('check',{}).get('issue',{}).get('impactSummary',[]) or '''''' + if data.get('data',{}).get('auto',{}).get('assessment',{}).get('applicationRef',[]) and data.get('data',{}).get('auto',{}).get('assessment',{}).get('ref',[]) and content.get('checkId',[]): + url = f"https://app.nowsecure.com/app/{data.get('data',{}).get('auto',{}).get('assessment',{}).get('applicationRef',[])}/assessment/{data.get('data',{}).get('auto',{}).get('assessment',{}).get('ref',[])}?viewObservationsBy=categories&viewFindingsBy=policyCategory#{content.get('checkId',[])}" + steps_to_reproduce = (content.get('check',{}).get('issue',{}).get('stepsToReproduce',[]) or '''''') + if content.get('check',{}).get('issue',{}).get('codeSamples',[]): code_samples = '''''' - for code_sample in content.get('check',{}).get('issue',{}).get('codeSamples',[]): - code_samples += f'''**{code_sample['platform']}**: {code_sample['caption']}\n```{code_sample['syntax']}\n{code_sample['block']}\n```\n''' + for code_sample in content.get('check',{}).get('issue',{}).get('codeSamples',{}): + code_samples += f'''**{code_sample.get('platform',[])}**: {code_sample.get('caption',[])}\n```{code_sample.get('syntax',[])}\n{code_sample.get('block',[])}\n```\n''' if code_samples: steps_to_reproduce += code_samples references = '''''' - if content['check']['issue']['guidanceLinks']: + if content.get('check',{}).get('issue',{}).get('guidanceLinks',[]): references+="### Guidance Links\n" for reference in content.get('check',{}).get('issue',{}).get('guidanceLinks',[]): - references+=f'''* [{reference['caption']}]({reference['url']})\n''' + references+=f'''* [{reference.get('caption',[])}]({reference.get('url',[])})\n''' cwe = None - if content['check']['issue']['regulations']: + if content.get('check',{}).get('issue',{}).get('regulations',[]): references+="### Regulations\n" - for regulation in content.get('check',{}).get('issue',{}).get('regulations',[]): - if regulation['type'] == 'cwe': - cwe = regulation['links'][0]['title'] - for link in regulation['links']: - references+=f"* **{regulation['label']}**: [{link['title']}]({link['url']})\n" + for regulation in content.get('check',{}).get('issue',{}).get('regulations',{}): + if regulation.get('type',[]) == 'cwe': + cwe = regulation.get('links',[])[0].get('title',[]) + for link in regulation.get('links',{}): + references+=f"* **{regulation.get('label',[])}**: [{link.get('title',[])}]({link.get('url',[])})\n" cve = None cve_pattern = r'CVE-\d{4}-\d{4,7}' cve_matches = re.findall(cve_pattern, title) diff --git a/unittests/tools/test_nowsecure_parser.py b/unittests/tools/test_nowsecure_parser.py index cf2ba3222ee..818b66de141 100644 --- a/unittests/tools/test_nowsecure_parser.py +++ b/unittests/tools/test_nowsecure_parser.py @@ -22,10 +22,8 @@ def test_nowsecure_parser_with_one_vuln_has_one_findings(self): endpoint.clean() self.assertEqual(1, len(findings)) self.assertEqual("App Configuration Allows Insecure Network Connections", findings[0].title) - self.assertEqual("The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.", findings[0].description) - self.assertEqual("high".capitalize(), findings[0].severity) - self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", findings[0].cvssv3) - self.assertEqual("The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).", findings[0].mitigation) + self.assertMultiLineEqual('''The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.''', findings[0].description) + self.assertMultiLineEqual('''The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).''', findings[0].mitigation) self.assertEqual("Allowing cleartext network connections allows attackers to intercept, inspect or manipulate data transmitted between the app and external servers, compromising the integrity and confidentiality of user information. This vulnerability can have serious business implications, particularly in the event of a data breach, including loss of customer trust, potential legal liabilities and financial penalties.", findings[0].impact) @@ -40,8 +38,6 @@ def test_nowsecure_parser_with_many_vuln_has_many_findings(self): self.assertEqual(5, len(findings)) self.assertEqual("App Configuration Allows Insecure Network Connections", findings[0].title) self.assertEqual("WebViews Allowing Access to Local Files", findings[1].title) - self.assertEqual("The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.", findings[0].description) - self.assertEqual("high".capitalize(), findings[0].severity) - self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", findings[0].cvssv3) - self.assertEqual("The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).", findings[0].mitigation) + self.assertMultiLineEqual(f'''The app utilizes insecure settings to permit cleartext network connections.\n\nCleartext connections transmit data unencrypted, which may expose sensitive information (such as passwords or credit card details) to attackers and leave the app vulnerable to man-in-the-middle attacks.\n\nBy default, Android prohibits cleartext connections (e.g., HTTP, FTP, WebSockets, XMPP, IMAP, SMTP) in apps installed on devices running Android 9 (API 28) or above. However, app developers have two main ways allow cleartext connections:\n\n- **Android Manifest:** whenever `android:usesCleartextTraffic` is set to `true` in the `` element of the Android manifest file.\n- **Network Security Config:** by setting the attribute `cleartextTrafficPermitted` to `true` within the `` element of the Network Security Config to enable cleartext traffic globally for the app or within `` for a more fine-grained approach, which would enable cleartext traffic only to specific domains and their subdomains.\n\nIf a Network Security Config is provided, all cleartext traffic rules in the Android Manifest will be overridden.''', findings[0].description) + self.assertMultiLineEqual('''The evidence table lists all configurations that allow cleartext network traffic:\n\n- **Source:** the file type that allows insecure access\n- **XML Element:** the XML element in the Android Manifest (``) or Network Security Configuration `` or ``)\n- **XML Attribute:** the XML attribute allowing cleartext traffic in the Android Manifest (`android:usesCleartextTraffic`) or Network Security Configuration `cleartextTrafficPermitted`)\n- **Uses SDK Default:** states if the Android SDK version's default value was used\n- **Allow Cleartext:** value of either `android:usesCleartextTraffic` or `cleartextTrafficPermitted` attributes indicating whether cleartext data is allowed\n- **Domain:** the domain that allows cleartext data (only present if is used)\n- **Includes Subdomains:** value of the `includeSubdomains` attribute indicating whether cleartext data is allowed for subdomains (only present if is used)\n\nTo mitigate this issue, we recommend the following:\n\n1. **Set `minSdkVersion` to 28 or higher in `build.gradle`**: To ensure that secure defaults are enforced, configure the `minSdkVersion` to 28 or above. This will prevent installation on devices that do not support secure defaults by default.\n\n```gradle\nandroid {\n defaultConfig {\n minSdkVersion 28\n }\n}\n```\n\n**Note**: The current Android [documentation](https://developer.android.com/privacy-and-security/security-config#CleartextTrafficPermitted) states that apps targeting API 28 or above (`targetSdkVersion`) will use secure defaults. However, **this is not always the case**. Despite targeting a higher SDK, devices running API 27 or lower continue to use insecure default values, even when an app's `targetSdkVersion` is set to a secure API level. Setting a `minSdkVersion` above 27 prevents the app from being installed on devices running Android 8.1 (API 27) or lower.\n\n2. **Enforce Explicit Security Configurations**: While upgrading the `minSdkVersion` is the preferred approach to ensure secure default values, the Android Manifest and Network Security Config can ensure that explicit incorrect cleartext traffic configurations are not allowed. This step also adds an extra layer of protection if upgrading the `minSdkVersion` is not feasible (e.g., for compatibility or to maintain support for a broader user base):\n\n- **Update `AndroidManifest.xml`**: Ensure that the attribute `android:usesCleartextTraffic` is present and set to `false`.\n\n ```xml\n \n ...\n \n ```\n\n- **Network Security Config (`network_security_config.xml`)**: If a custom `android:networkSecurityConfig` file is used (typically in `res/xml/network_security_config.xml`), ensure that the `base-config` and all `domain-config` entries have `cleartextTrafficPermitted` set to `false`:\n\n ```xml\n \n \n ...\n \n \n ...\n \n \n ```\n\n**Cleartext Exception Considerations**: If cleartext connections are essential for specific domains (e.g., for backend compatibility), consider limiting cleartext traffic strictly to those domains. Note, however, that this introduces **significant security risks**, and whenever possible, backends should support secure connections (HTTPS).\n\n**Limitations of `isCleartextTrafficPermitted`**: Although setting `isCleartextTrafficPermitted` improves security for most network traffic, it [may not prevent all cleartext communications](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted()) (e.g., those initiated through low-level sockets). This configuration is enforced on a best-effort basis and applies primarily to higher-level network APIs such as [`HttpsURLConnection`](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection).''', findings[0].mitigation) self.assertEqual("Allowing cleartext network connections allows attackers to intercept, inspect or manipulate data transmitted between the app and external servers, compromising the integrity and confidentiality of user information. This vulnerability can have serious business implications, particularly in the event of a data breach, including loss of customer trust, potential legal liabilities and financial penalties.", findings[0].impact)