From 941d7fad5ce4bc8cbdba840b198a6e17dff19946 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 21 Oct 2024 15:28:54 +0000 Subject: [PATCH 01/38] Update versions in application files --- components/package.json | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/package.json b/components/package.json index f0e2d5af2c..06cdce1889 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.39.2", + "version": "2.40.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 95d4a96d0b..ae1c256e0e 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.39.2" +appVersion: "2.40.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.155 +version: 1.6.156-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 7360f48da2411099e821bbefc56ca278e60d9584 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 06:56:13 +0200 Subject: [PATCH 02/38] Bump boto3 from 1.35.43 to 1.35.45 (#11119) Bumps [boto3](https://github.com/boto/boto3) from 1.35.43 to 1.35.45. - [Release notes](https://github.com/boto/boto3/releases) - [Commits](https://github.com/boto/boto3/compare/1.35.43...1.35.45) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d1e0c9a75d..20e75fdda9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -69,7 +69,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.35.43 # Required for Celery Broker AWS (SQS) support +boto3==1.35.45 # Required for Celery Broker AWS (SQS) support netaddr==1.3.0 vulners==2.2.2 fontawesomefree==6.6.0 From f72614d5b7c4f07c3eb7094b0bee447ea859109b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 06:57:12 +0200 Subject: [PATCH 03/38] Bump packageurl-python from 0.15.6 to 0.16.0 (#11118) Bumps [packageurl-python](https://github.com/package-url/packageurl-python) from 0.15.6 to 0.16.0. - [Release notes](https://github.com/package-url/packageurl-python/releases) - [Changelog](https://github.com/package-url/packageurl-python/blob/main/CHANGELOG.rst) - [Commits](https://github.com/package-url/packageurl-python/compare/v0.15.6...v0.16.0) --- updated-dependencies: - dependency-name: packageurl-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 20e75fdda9..a52c461dc0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -48,7 +48,7 @@ social-auth-core==4.5.4 gitpython==3.1.43 python-gitlab==4.13.0 cpe==1.3.1 -packageurl-python==0.15.6 +packageurl-python==0.16.0 django-crum==0.7.9 JSON-log-formatter==1.1 django-split-settings==1.3.2 From b6a61bcd01f9c0c8c0d2e9ecc56f7a0313ad5e2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:08:40 +0200 Subject: [PATCH 04/38] Bump vulners from 2.2.2 to 2.2.3 (#11105) Bumps vulners from 2.2.2 to 2.2.3. --- updated-dependencies: - dependency-name: vulners dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a52c461dc0..f69114a744 100644 --- a/requirements.txt +++ b/requirements.txt @@ -71,6 +71,6 @@ blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support boto3==1.35.45 # Required for Celery Broker AWS (SQS) support netaddr==1.3.0 -vulners==2.2.2 +vulners==2.2.3 fontawesomefree==6.6.0 PyYAML==6.0.2 From e98d81d7f6c1b06b22c22ba5b2bc595e04f34b92 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 09:55:47 -0500 Subject: [PATCH 05/38] Update gcr.io/cloudsql-docker/gce-proxy Docker tag from 1.37.0 to v1.37.1 (helm/defectdojo/values.yaml) (#11120) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- helm/defectdojo/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/defectdojo/values.yaml b/helm/defectdojo/values.yaml index 67c41eeab3..b2d0422bc2 100644 --- a/helm/defectdojo/values.yaml +++ b/helm/defectdojo/values.yaml @@ -454,7 +454,7 @@ cloudsql: image: # set repo and image tag of gce-proxy repository: gcr.io/cloudsql-docker/gce-proxy - tag: 1.37.0 + tag: 1.37.1 pullPolicy: IfNotPresent # set CloudSQL instance: 'project:zone:instancename' instance: "" From 2311f5f49695175584bf595b2cda65ce1314daef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:01:54 -0500 Subject: [PATCH 06/38] Bump cryptography from 43.0.1 to 43.0.3 (#11106) Bumps [cryptography](https://github.com/pyca/cryptography) from 43.0.1 to 43.0.3. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/43.0.1...43.0.3) --- updated-dependencies: - dependency-name: cryptography dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f69114a744..a70ef4f810 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,7 +32,7 @@ Markdown==3.7 openpyxl==3.1.5 Pillow==11.0.0 # required by django-imagekit psycopg[c]==3.2.3 -cryptography==43.0.1 +cryptography==43.0.3 python-dateutil==2.9.0.post0 pytz==2024.2 redis==5.1.1 From 9bf5329f63506289ccdeeddd6226bd3f8a7d57f4 Mon Sep 17 00:00:00 2001 From: Adam Bertrand Date: Thu, 24 Oct 2024 17:15:45 +0200 Subject: [PATCH 07/38] Parser: Add support for importing json exports from the PTART Reporting Tool (#11038) * Initial template * Add scan file sample * Fix the basic structure of the parser * Begin unit tests and assessment parser * Fix up json files and refactor to just use findings. Group by component for the Assessment names * Use self.subTest to work out findings * Add test cases * update test files * Add support for tags and enpoints * Add files * Finish Assessment parser * Fix bugs with CVSS vector and tool id * Fix a unit test * Add PTART Deduplication settings * Add retest campaigns * Refactor and robustify screenshot parsing * Robustify attachements and screenshot naming * Refactor generation of the description * Robustify the import to avoid crashing and add comments * Add Documentation * Refactor code to implement proper guards and pythonic simplifications * Nuke unused test code * Fix formatting to flake8 standards * Fix ruff errors * Add vulnerability id from tool to vulnerability ID field * Add support for references * Add tests and fix references * fix linter complaint * fix scan files to be more representative * Update settings sha256 --- .../en/integrations/parsers/file/ptart.md | 14 + dojo/settings/.settings.dist.py.sha256sum | 2 +- dojo/settings/settings.dist.py | 1 + dojo/tools/ptart/__init__.py | 0 dojo/tools/ptart/assessment_parser.py | 62 ++ dojo/tools/ptart/parser.py | 77 ++ dojo/tools/ptart/ptart_parser_tools.py | 187 +++++ dojo/tools/ptart/retest_parser.py | 102 +++ unittests/scans/ptart/empty_with_error.json | 1 + unittests/scans/ptart/ptart_many_vul.json | 84 +++ unittests/scans/ptart/ptart_one_vul.json | 71 ++ .../scans/ptart/ptart_vuln_plus_retest.json | 125 ++++ .../ptart_vulns_with_mult_assessments.json | 107 +++ unittests/scans/ptart/ptart_zero_vul.json | 26 + unittests/tools/test_ptart_parser.py | 694 ++++++++++++++++++ 15 files changed, 1552 insertions(+), 1 deletion(-) create mode 100644 docs/content/en/integrations/parsers/file/ptart.md create mode 100644 dojo/tools/ptart/__init__.py create mode 100644 dojo/tools/ptart/assessment_parser.py create mode 100644 dojo/tools/ptart/parser.py create mode 100644 dojo/tools/ptart/ptart_parser_tools.py create mode 100644 dojo/tools/ptart/retest_parser.py create mode 100644 unittests/scans/ptart/empty_with_error.json create mode 100644 unittests/scans/ptart/ptart_many_vul.json create mode 100644 unittests/scans/ptart/ptart_one_vul.json create mode 100644 unittests/scans/ptart/ptart_vuln_plus_retest.json create mode 100644 unittests/scans/ptart/ptart_vulns_with_mult_assessments.json create mode 100644 unittests/scans/ptart/ptart_zero_vul.json create mode 100644 unittests/tools/test_ptart_parser.py diff --git a/docs/content/en/integrations/parsers/file/ptart.md b/docs/content/en/integrations/parsers/file/ptart.md new file mode 100644 index 0000000000..5ce5696749 --- /dev/null +++ b/docs/content/en/integrations/parsers/file/ptart.md @@ -0,0 +1,14 @@ +--- +title: "PTART Reports" +toc_hide: true +--- + +### What is PTART? +PTART is a Pentest and Security Auditing Reporting Tool developed by the Michelin CERT (https://github.com/certmichelin/PTART) + +### Importing Reports +Reports can be exported to JSON format from the PTART web UI, and imported into DefectDojo by using the "PTART Report" importer. + +### Sample Scan Data +Sample scan data for testing purposes can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/ptart). + diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index 476d3116d4..205a351a62 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -42026ac47884ee26fe742e59fb7dc621b5f927ee6ee3c92daf09b97f2a740163 +2a5a93d6f848564c83e0a916ca3fa64a0467c413e50bc1da5be51d0c3c1e7f14 diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 1493afadd9..98de4650a5 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1514,6 +1514,7 @@ def saml2_attrib_map_format(dict): "ThreatComposer Scan": DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL_OR_HASH_CODE, "Invicti Scan": DEDUPE_ALGO_HASH_CODE, "KrakenD Audit Scan": DEDUPE_ALGO_HASH_CODE, + "PTART Report": DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL, } # Override the hardcoded settings here via the env var diff --git a/dojo/tools/ptart/__init__.py b/dojo/tools/ptart/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dojo/tools/ptart/assessment_parser.py b/dojo/tools/ptart/assessment_parser.py new file mode 100644 index 0000000000..02387a7d65 --- /dev/null +++ b/dojo/tools/ptart/assessment_parser.py @@ -0,0 +1,62 @@ +import dojo.tools.ptart.ptart_parser_tools as ptart_tools +from dojo.models import Finding + + +class PTARTAssessmentParser: + def __init__(self): + self.cvss_type = None + + def get_test_data(self, tree): + # Check that the report is valid, If we have no assessments, then + # return an empty list + if "assessments" not in tree: + return [] + + self.cvss_type = tree.get("cvss_type", None) + assessments = tree["assessments"] + return [finding for assessment in assessments + for finding in self.parse_assessment(assessment)] + + def parse_assessment(self, assessment): + hits = assessment.get("hits", []) + return [self.get_finding(assessment, hit) for hit in hits] + + def get_finding(self, assessment, hit): + effort = ptart_tools.parse_ptart_fix_effort(hit.get("fix_complexity")) + finding = Finding( + title=ptart_tools.parse_title_from_hit(hit), + severity=ptart_tools.parse_ptart_severity(hit.get("severity")), + effort_for_fixing=effort, + component_name=assessment.get("title", "Unknown Component"), + date=ptart_tools.parse_date_added_from_hit(hit), + ) + + # Don't add fields if they are blank + if hit["body"]: + finding.description = hit.get("body") + + if hit["remediation"]: + finding.mitigation = hit.get("remediation") + + if hit["id"]: + finding.unique_id_from_tool = hit.get("id") + finding.vuln_id_from_tool = hit.get("id") + finding.cve = hit.get("id") + + # Clean up and parse the CVSS vector + cvss_vector = ptart_tools.parse_cvss_vector(hit, self.cvss_type) + if cvss_vector: + finding.cvssv3 = cvss_vector + + if "labels" in hit: + finding.unsaved_tags = hit["labels"] + + finding.unsaved_endpoints = ptart_tools.parse_endpoints_from_hit(hit) + + # Add screenshots to files, and add other attachments as well. + finding.unsaved_files = ptart_tools.parse_screenshots_from_hit(hit) + finding.unsaved_files.extend(ptart_tools.parse_attachment_from_hit(hit)) + + finding.references = ptart_tools.parse_references_from_hit(hit) + + return finding diff --git a/dojo/tools/ptart/parser.py b/dojo/tools/ptart/parser.py new file mode 100644 index 0000000000..c52ebf4fb4 --- /dev/null +++ b/dojo/tools/ptart/parser.py @@ -0,0 +1,77 @@ +import json + +import dojo.tools.ptart.ptart_parser_tools as ptart_tools +from dojo.tools.parser_test import ParserTest +from dojo.tools.ptart.assessment_parser import PTARTAssessmentParser +from dojo.tools.ptart.retest_parser import PTARTRetestParser + + +class PTARTParser: + + """ + Imports JSON reports from the PTART reporting tool + (https://github.com/certmichelin/PTART) + """ + + def get_scan_types(self): + return ["PTART Report"] + + def get_label_for_scan_types(self, scan_type): + return "PTART Report" + + def get_description_for_scan_types(self, scan_type): + return "Import a PTART report file in JSON format." + + def get_tests(self, scan_type, scan): + data = json.load(scan) + + test = ParserTest( + name="Pen Test Report", + type="Pen Test", + version="", + ) + + # We set both to the same value for now, setting just the name doesn't + # seem to display when imported. This may cause issues with the UI in + # the future, but there's not much (read no) documentation on this. + if "name" in data: + test.name = data["name"] + " Report" + test.type = data["name"] + " Report" + + # Generate a description from the various fields in the report data + description = ptart_tools.generate_test_description_from_report(data) + + # Check that the fields are filled, otherwise don't set the description + if description: + test.description = description + + # Setting the dates doesn't seem to want to work in reality :( + # Perhaps in a future version of DefectDojo? + if "start_date" in data: + test.target_start = ptart_tools.parse_date( + data["start_date"], "%Y-%m-%d", + ) + + if "end_date" in data: + test.target_end = ptart_tools.parse_date( + data["end_date"], "%Y-%m-%d", + ) + + findings = self.get_items(data) + test.findings = findings + return [test] + + def get_findings(self, file, test): + data = json.load(file) + return self.get_items(data) + + def get_items(self, data): + # We have several main sections in the report json: Assessments and + # Retest Campaigns. I haven't been able to create multiple tests for + # each section, so we'll just merge them for now. + findings = PTARTAssessmentParser().get_test_data(data) + findings.extend(PTARTRetestParser().get_test_data(data)) + return findings + + def requires_file(self, scan_type): + return True diff --git a/dojo/tools/ptart/ptart_parser_tools.py b/dojo/tools/ptart/ptart_parser_tools.py new file mode 100644 index 0000000000..f538a81f3c --- /dev/null +++ b/dojo/tools/ptart/ptart_parser_tools.py @@ -0,0 +1,187 @@ +import pathlib +from datetime import datetime + +import cvss + +from dojo.models import Endpoint + +ATTACHMENT_ERROR = "Attachment data not found" +SCREENSHOT_ERROR = "Screenshot data not found" + + +def parse_ptart_severity(severity): + severity_mapping = { + 1: "Critical", + 2: "High", + 3: "Medium", + 4: "Low", + } + return severity_mapping.get(severity, "Info") # Default severity + + +def parse_ptart_fix_effort(effort): + effort_mapping = { + 1: "High", + 2: "Medium", + 3: "Low", + } + return effort_mapping.get(effort, None) + + +def parse_title_from_hit(hit): + hit_title = hit.get("title", None) + hit_id = hit.get("id", None) + + return f"{hit_id}: {hit_title}" \ + if hit_title and hit_id \ + else (hit_title or hit_id or "Unknown Hit") + + +def parse_date_added_from_hit(hit): + PTART_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" + date_added = hit.get("added", None) + return parse_date(date_added, PTART_DATETIME_FORMAT) + + +def parse_date(date, format): + try: + return datetime.strptime(date, format) if date else datetime.now() + except ValueError: + return datetime.now() + + +def parse_cvss_vector(hit, cvss_type): + cvss_vector = hit.get("cvss_vector", None) + # Defect Dojo Only supports CVSS v3 for now. + if cvss_vector: + # Similar application once CVSS v4 is supported + if cvss_type == 3: + try: + c = cvss.CVSS3(cvss_vector) + return c.clean_vector() + except cvss.CVSS3Error: + return None + return None + + +def parse_retest_status(status): + fix_status_mapping = { + "F": "Fixed", + "NF": "Not Fixed", + "PF": "Partially Fixed", + "NA": "Not Applicable", + "NT": "Not Tested", + } + return fix_status_mapping.get(status, None) + + +def parse_screenshots_from_hit(hit): + if "screenshots" not in hit: + return [] + screenshots = [parse_screenshot_data(screenshot) + for screenshot in hit["screenshots"]] + return [ss for ss in screenshots if ss is not None] + + +def parse_screenshot_data(screenshot): + try: + title = get_screenshot_title(screenshot) + data = get_screenshot_data(screenshot) + return { + "title": title, + "data": data, + } + except ValueError: + return None + + +def get_screenshot_title(screenshot): + caption = screenshot.get("caption", "screenshot") + if not caption: + caption = "screenshot" + return f"{caption}{get_file_suffix_from_screenshot(screenshot)}" + + +def get_screenshot_data(screenshot): + if ("screenshot" not in screenshot + or "data" not in screenshot["screenshot"] + or not screenshot["screenshot"]["data"]): + raise ValueError(SCREENSHOT_ERROR) + return screenshot["screenshot"]["data"] + + +def get_file_suffix_from_screenshot(screenshot): + return pathlib.Path(screenshot["screenshot"]["filename"]).suffix \ + if ("screenshot" in screenshot + and "filename" in screenshot["screenshot"]) \ + else "" + + +def parse_attachment_from_hit(hit): + if "attachments" not in hit: + return [] + files = [parse_attachment_data(attachment) + for attachment in hit["attachments"]] + return [f for f in files if f is not None] + + +def parse_attachment_data(attachment): + try: + title = get_attachement_title(attachment) + data = get_attachment_data(attachment) + return { + "title": title, + "data": data, + } + except ValueError: + # No data in attachment, let's not import this file. + return None + + +def get_attachment_data(attachment): + if "data" not in attachment or not attachment["data"]: + raise ValueError(ATTACHMENT_ERROR) + return attachment["data"] + + +def get_attachement_title(attachment): + title = attachment.get("title", "attachment") + if not title: + title = "attachment" + return title + + +def parse_endpoints_from_hit(hit): + if "asset" not in hit or not hit["asset"]: + return [] + endpoint = Endpoint.from_uri(hit["asset"]) + return [endpoint] + + +def generate_test_description_from_report(data): + keys = ["executive_summary", "engagement_overview", "conclusion"] + clauses = [clause for clause in [data.get(key) for key in keys] if clause] + description = "\n\n".join(clauses) + return description or None + + +def parse_references_from_hit(hit): + if "references" not in hit: + return None + + references = hit.get("references", []) + all_refs = [get_transformed_reference(ref) for ref in references] + clean_refs = [tref for tref in all_refs if tref] + if not clean_refs: + return None + return "\n".join(clean_refs) + + +def get_transformed_reference(reference): + title = reference.get("name", "Reference") + url = reference.get("url", None) + if not url: + if not title: + return url + return None + return f"{title}: {url}" diff --git a/dojo/tools/ptart/retest_parser.py b/dojo/tools/ptart/retest_parser.py new file mode 100644 index 0000000000..812a458344 --- /dev/null +++ b/dojo/tools/ptart/retest_parser.py @@ -0,0 +1,102 @@ +import dojo.tools.ptart.ptart_parser_tools as ptart_tools +from dojo.models import Finding + + +def generate_retest_hit_title(hit, original_hit): + # Fake a title for the retest hit with the fix status if available + title = original_hit.get("title", "") + hit_id = hit.get("id", None) + if "status" in hit: + title = f"{title} ({ptart_tools.parse_retest_status(hit['status'])})" + fake_retest_hit = { + "title": title, + "id": hit_id, + } + return ptart_tools.parse_title_from_hit(fake_retest_hit) + + +class PTARTRetestParser: + def __init__(self): + self.cvss_type = None + + def get_test_data(self, tree): + if "retests" in tree: + self.cvss_type = tree.get("cvss_type", None) + retests = tree["retests"] + else: + return [] + + return [finding for retest in retests + for finding in self.parse_retest(retest)] + + def parse_retest(self, retest): + hits = retest.get("hits", []) + # Get all the potential findings, valid or not. + all_findings = [self.get_finding(retest, hit) for hit in hits] + # We want to make sure we include only valid findings for a retest. + return [finding for finding in all_findings if finding is not None] + + def get_finding(self, retest, hit): + + # The negatives are a bit confusing, but we want to skip hits that + # don't have an original hit. Hit is invalid in a retest if not linked + # to an original. + if "original_hit" not in hit or not hit["original_hit"]: + return None + + # Get the original hit from the retest + original_hit = hit["original_hit"] + + # Set the Finding title to the original hit title with the retest + # status if available. We don't really have any other places to set + # this field. + finding_title = generate_retest_hit_title(hit, original_hit) + + # As the retest hit doesn't have a date added, use the start of the + # retest campaign as something that's close enough. + finding = Finding( + title=finding_title, + severity=ptart_tools.parse_ptart_severity( + original_hit.get("severity"), + ), + effort_for_fixing=ptart_tools.parse_ptart_fix_effort( + original_hit.get("fix_complexity"), + ), + component_name=f"Retest: {retest.get('name', 'Retest')}", + date=ptart_tools.parse_date( + retest.get("start_date"), + "%Y-%m-%d", + ), + ) + + # Don't add the fields if they are blank. + if hit["body"]: + finding.description = hit.get("body") + + if original_hit["remediation"]: + finding.mitigation = original_hit.get("remediation") + + if hit["id"]: + finding.unique_id_from_tool = hit.get("id") + finding.vuln_id_from_tool = original_hit.get("id") + finding.cve = original_hit.get("id") + + cvss_vector = ptart_tools.parse_cvss_vector( + original_hit, + self.cvss_type, + ) + if cvss_vector: + finding.cvssv3 = cvss_vector + + if "labels" in original_hit: + finding.unsaved_tags = original_hit["labels"] + + finding.unsaved_endpoints = ptart_tools.parse_endpoints_from_hit( + original_hit, + ) + + # We only have screenshots in a retest. Refer to the original hit for + # the attachments. + finding.unsaved_files = ptart_tools.parse_screenshots_from_hit(hit) + + return finding diff --git a/unittests/scans/ptart/empty_with_error.json b/unittests/scans/ptart/empty_with_error.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/unittests/scans/ptart/empty_with_error.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/unittests/scans/ptart/ptart_many_vul.json b/unittests/scans/ptart/ptart_many_vul.json new file mode 100644 index 0000000000..1e6afebcff --- /dev/null +++ b/unittests/scans/ptart/ptart_many_vul.json @@ -0,0 +1,84 @@ +{ + "name": "Test", + "executive_summary": "Mistakes were made", + "engagement_overview": "Things were done", + "conclusion": "Things should be put right", + "scope": "test.example.com", + "client": "Test Client", + "start_date": "2024-08-11", + "end_date": "2024-08-16", + "cvss_type": 3, + "tools": [ + "Burp Suite" + ], + "methodologies": [ + "OWASP Testing Guide V4.2" + ], + "pentesters": [ + { + "username": "hydragyrum", + "first_name": "", + "last_name": "" + } + ], + "assessments": [ + { + "title": "Test Assessment", + "hits": [ + { + "id": "PTART-2024-00002", + "title": "Broken Access Control", + "body": "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + "remediation": "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + "asset": "https://test.example.com", + "severity": 2, + "fix_complexity": 3, + "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + "cvss_score": "10.0", + "added": "2024-09-06T03:33:07.908", + "labels": [ + "A01:2021-Broken Access Control", + "A04:2021-Insecure Design" + ], + "screenshots": [ + { + "caption": "Borked", + "order": 0, + "screenshot": { + "filename": "screenshots/a78bebcc-6da7-4c25-86a3-441435ea68d0.png", + "data": "iVBORw0KGgoAAAANSUhEUgAABs4AAAE2CAYAAADBHGdHAAAMP2lDQ1BJQ0MgUHJvZmlsZQAASImVVwdYU8kWnltSIbQAAlJCb4KIlABSQmgBpBdBVEISIJQYA0HFjiwquBZULGBDV0UUOyAWFLGzKPa+WFBQ1sWCXXmTArruK9+bfDPz558z/zlz7twyAKif4IrFOagGALmifElMsD9jXFIyg9QNyPBHBQCYcHl5YlZUVDjEYLD/e3l3AyCy/qqDTOuf4/+1aPIFeTwAkCiI0/h5vFyIDwKAV/HEknwAiDLefGq+WIZhBdoSGCDEC2U4Q4GrZDhNgffKbeJi2BC3AkBW5XIlGQCoXYY8o4CXATXU+iB2EvGFIgDUGRD75OZO5kOcCrENtBFDLNNnpv2gk/E3zbQhTS43Ywgr1iIv5ABhnjiHO/3/TMf/Lrk50kEfVrCqZkpCYmRrhnm7lT05TIZVIe4VpUVEQqwF8QchX24PMUrNlIbEK+xRQ14eG+YM6ELsxOcGhEFsCHGQKCciXMmnpQuDOBDDHYJOE+Zz4iDWg3ihIC8wVmmzSTI5RukLrU+XsFlK/hxXIvcr8/VAmh3PUuq/zhRwlPqYWmFmXCLEcK9hFgXChAiI1SB2zMuODVPajCnMZEcM2kikMbL4LSCOEYiC/RX6WEG6JChGaV+amze4XmxTppATocT78zPjQhT5wVp5XHn8cC3YZYGIFT+oI8gbFz64Fr4gIFCxdqxbIIqPVep8EOf7xyjm4lRxTpTSHjcT5ATLeDOIXfIKYpVz8YR8uCEV+ni6OD8qThEnXpjFDY1SxIMvA+GADQIAA0hhTQOTQRYQtvc29MJ/ipEgwAUSkAEEwEHJDM5IlI+IYBsLCsGfEAlA3tA8f/moABRA/usQq2gdQLp8tEA+Ixs8hTgXhIEc+F8qnyUa8pYAnkBG+A/vXFh5MN4cWGXj/54fZL8zLMiEKxnpoEeG+qAlMZAYQAwhBhFtcQPcB/fCw2HrB6szzsQ9Btfx3Z7wlNBBeES4Tugk3J4kLJL8FOVY0An1g5S5SPsxF7gV1HTF/XFvqA6VcV3cADjgLtAPC/eFnl0hy1bGLcsK4yftv63gh6uhtKM4UVDKMIofxebnmWp2aq5DKrJc/5gfRaxpQ/lmD4387J/9Q/b5sA/72RJbiB3AzmInsfPYUawBMLBmrBFrw47J8NDueiLfXYPeYuTxZEMd4T/8DV5ZWSbznGqdepy+KMbyBdNkz2jAniyeLhFmZOYzWPCNIGBwRDzHEQxnJ2cXAGTvF8Xj6020/L2B6LZ95+b/AYB388DAwJHvXGgzAPvc4e1/+Dtnw4SvDhUAzh3mSSUFCg6XNQT4lFCHd5o+MAbmwAauxxm4AS/gBwJBKIgEcSAJTITRZ8J9LgFTwUwwD5SAMrAMrALrwEawBewAu8F+0ACOgpPgDLgILoPr4C7cPV3gBegD78BnBEFICA2hI/qICWKJ2CPOCBPxQQKRcCQGSUJSkQxEhEiRmch8pAwpR9Yhm5EaZB9yGDmJnEc6kNvIQ6QHeY18QjFUFdVGjVArdCTKRFloGBqHTkAz0CloIVqMLkHXoNXoLrQePYleRK+jnegLtB8DmAqmi5liDhgTY2ORWDKWjkmw2VgpVoFVY3VYE7zOV7FOrBf7iBNxOs7AHeAODsHjcR4+BZ+NL8bX4TvwerwVv4o/xPvwbwQawZBgT/AkcAjjCBmEqYQSQgVhG+EQ4TS8l7oI74hEoi7RmugO78UkYhZxBnExcT1xD/EEsYP4mNhPIpH0SfYkb1IkiUvKJ5WQ1pJ2kZpJV0hdpA9kFbIJ2ZkcRE4mi8hF5AryTvJx8hXyM/JnigbFkuJJiaTwKdMpSylbKU2US5QuymeqJtWa6k2No2ZR51HXUOuop6n3qG9UVFTMVDxUolWEKnNV1qjsVTmn8lDlo6qWqp0qWzVFVaq6RHW76gnV26pvaDSaFc2PlkzLpy2h1dBO0R7QPqjR1RzVOGp8tTlqlWr1alfUXqpT1C3VWeoT1QvVK9QPqF9S79WgaFhpsDW4GrM1KjUOa9zU6Neka47SjNTM1VysuVPzvGa3FknLSitQi69VrLVF65TWYzpGN6ez6Tz6fPpW+ml6lzZR21qbo52lXaa9W7tdu09HS8dFJ0Fnmk6lzjGdTl1M10qXo5uju1R3v+4N3U/DjIaxhgmGLRpWN+zKsPd6w/X89AR6pXp79K7rfdJn6AfqZ+sv12/Qv2+AG9gZRBtMNdhgcNqgd7j2cK/hvOGlw/cPv2OIGtoZxhjOMNxi2GbYb2RsFGwkNlprdMqo11jX2M84y3il8XHjHhO6iY+J0GSlSbPJc4YOg8XIYaxhtDL6TA1NQ0ylpptN200/m1mbxZsVme0xu29ONWeap5uvNG8x77MwsRhrMdOi1uKOJcWSaZlpudryrOV7K2urRKsFVg1W3dZ61hzrQuta63s2NBtfmyk21TbXbIm2TNts2/W2l+1QO1e7TLtKu0v2qL2bvdB+vX3HCMIIjxGiEdUjbjqoOrAcChxqHR466jqGOxY5Nji+HGkxMnnk8pFnR35zcnXKcdrqdHeU1qjQUUWjmka9drZz5jlXOl8bTRsdNHrO6MbRr1zsXQQuG1xuudJdx7oucG1x/erm7iZxq3PrcbdwT3Wvcr/J1GZGMRczz3kQPPw95ngc9fjo6eaZ77nf8y8vB69sr51e3WOsxwjGbB3z2NvMm+u92bvTh+GT6rPJp9PX1JfrW+37yM/cj++3ze8Zy5aVxdrFeunv5C/xP+T/nu3JnsU+EYAFBAeUBrQHagXGB64LfBBkFpQRVBvUF+waPCP4RAghJCxkechNjhGHx6nh9IW6h84KbQ1TDYsNWxf2KNwuXBLeNBYdGzp2xdh7EZYRooiGSBDJiVwReT/KOmpK1JFoYnRUdGX005hRMTNjzsbSYyfF7ox9F+cftzTubrxNvDS+JUE9ISWhJuF9YkBieWLnuJHjZo27mGSQJExqTCYlJyRvS+4fHzh+1fiuFNeUkpQbE6wnTJtwfqLBxJyJxyapT+JOOpBKSE1M3Zn6hRvJreb2p3HSqtL6eGzeat4Lvh9/Jb9H4C0oFzxL904vT+/O8M5YkdGT6ZtZkdkrZAvXCV9lhWRtzHqfHZm9PXsgJzFnTy45NzX3sEhLlC1qnWw8edrkDrG9uETcOcVzyqopfZIwybY8JG9CXmO+NvyQb5PaSH+RPizwKags+DA1YeqBaZrTRNPapttNXzT9WWFQ4W8z8Bm8GS0zTWfOm/lwFmvW5tnI7LTZLXPM5xTP6ZobPHfHPOq87Hm/FzkVlRe9nZ84v6nYqHhu8eNfgn+pLVErkZTcXOC1YONCfKFwYfui0YvWLvpWyi+9UOZUVlH2ZTFv8YVfR/265teBJelL2pe6Ld2wjLhMtOzGct/lO8o1ywvLH68Yu6J+JWNl6cq3qyatOl/hUrFxNXW1dHXnmvA1jWst1i5b+2Vd5rrrlf6Ve6oMqxZVvV/PX39lg9+Guo1GG8s2ftok3HRrc/Dm+mqr6ootxC0FW55uTdh69jfmbzXbDLaVbfu6XbS9c0fMjtYa95qanYY7l9aitdLanl0puy7vDtjdWOdQt3mP7p6yvWCvdO/zfan7buwP299ygHmg7qDlwapD9EOl9Uj99Pq+hsyGzsakxo7DoYdbmryaDh1xPLL9qOnRymM6x5Yepx4vPj7QXNjcf0J8ovdkxsnHLZNa7p4ad+paa3Rr++mw0+fOBJ05dZZ1tvmc97mj5z3PH77AvNBw0e1ifZtr26HfXX8/1O7WXn/J/VLjZY/LTR1jOo5f8b1y8mrA1TPXONcuXo+43nEj/satmyk3O2/xb3Xfzrn96k7Bnc93594j3Cu9r3G/4oHhg+o/bP/Y0+nWeexhwMO2R7GP7j7mPX7xJO/Jl67ip7SnFc9MntV0O3cf7Qnqufx8/POuF+IXn3tL/tT8s+qlzcuDf/n91dY3rq/rleTVwOvFb/TfbH/r8ralP6r/wbvcd5/fl37Q/7DjI/Pj2U+Jn559nvqF9GXNV9uvTd/Cvt0byB0YEHMlXPmnAAYrmp4OwOvtANCSAKDD8xl1vOL8Jy+I4swqR+A/YcUZUV7cAKiD3+/RvfDr5iYAe7fC4xfUV08BIIoGQJwHQEePHqqDZzX5uVJWiPAcsCnia1puGvg3RXHm/CHun3sgU3UBP/f/AgbLfEO2JYN/AAAAomVYSWZNTQAqAAAACAAGAQYAAwAAAAEAAgAAARIAAwAAAAEAAQAAARoABQAAAAEAAABWARsABQAAAAEAAABeASgAAwAAAAEAAgAAh2kABAAAAAEAAABmAAAAAAAAAJAAAAABAAAAkAAAAAEAA5KGAAcAAAASAAAAkKACAAQAAAABAAAGzqADAAQAAAABAAABNgAAAABBU0NJSQAAAFNjcmVlbnNob3SZB5rxAAAACXBIWXMAABYlAAAWJQFJUiTwAAADVGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8dGlmZjpDb21wcmVzc2lvbj4xPC90aWZmOkNvbXByZXNzaW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xNDQ8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjE0NDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6UGhvdG9tZXRyaWNJbnRlcnByZXRhdGlvbj4yPC90aWZmOlBob3RvbWV0cmljSW50ZXJwcmV0YXRpb24+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4xNzQyPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6VXNlckNvbW1lbnQ+U2NyZWVuc2hvdDwvZXhpZjpVc2VyQ29tbWVudD4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMxMDwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgoGj4CnAABAAElEQVR4AezdB3wURd/A8X86SYAQakIv0qs0KaJURUVUxI6iiA0UpAjYeETFjiBVULEhj+19EEQBQem99yY9dAIkQEJIAu/Mwm2u7CUhXJK78Jv3c9zszOzs7Hc3Pp/P/d+Z8bukkpAQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQuM4F/K/z++f2EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEDAECJzxIiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQCUUAAgbwtcOFErJyYv1jiFi+Tsxs35O2b5e58SiB/7ToS0byJFL21uQQXLeJTY2ewCCCAAAIIIIAAAggggAACCCCAAAIIIJA3BfwuqZQ3b427QgCB2MVL5fB3P8qFwwflYnKKXEpJAQUBrxHwCwwU/6BACY4uJdFPPCxFmjf1mrExEAQQQAABBBBAAAEEEEAAAQQQQAABBBC4PgWYcXZ9Pnfu+joQ0EGzQxMnSdLBGMlXoaJENGsiZR5/6Dq4c27RVwQOfP+TxC1ZJuf37DbeVT1ugme+8vQYJwIIIIAAAggggAACCCCAAAIIIIAAAnlTgMBZ3nyu3NV1LqCXZ9QzzXTQLKLJTVKswx0SXqnida7C7XubQFSH9lKgehU5Pn2GxC1bbryzBapWYdlGb3tQjAcBBBBAAAEEEEAAAQQQQAABBBBAAIHrSCBXAmcparm48+fPuzAHBQVJSEiIS3lWC1JTUyUxMdHldH9/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IYAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAII+KoAgTNffXKMGwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAwKMCBM48yklnCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACvipA4MxXnxzjRgABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQ8KgAgTOPctIZAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICArwoQOPPVJ8e4EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEPCpA4MyjnHSGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDgqwIEznz1yTFuBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABjwoQOPMoJ50hgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgj4qgCBM199cowbAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEDAowIEzjzKSWcIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAK+KkDgzFefHONGAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBDwqACBM49y0hkCCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggICvChA489Unx7gRQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQ8KkDgzKOcdIYAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIOCrAgTOfPXJMW4EEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAGPChA48ygnnSGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCPiqAIEzX31yjBsBBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQMCjAgTOPMpJZwgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAr4qQODMV58c40YAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEPCoAIEzj3LSGQIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgK8KEDjz1SfHuBFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBDwqQODMo5zZ39nadeuleu0bjU/Heztl/wW5AgIIIIAAAggggAACCCCAAAIIIIAAAggggAAC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kGcF0l9TMM/eNjeGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgKMAgTNHD44QQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSuUwECZ9fpg+e2EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEHAXyxB5njrfkfUfVqlaVO26/3RhYwwY3et8AGRECCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggID4XVIJBwQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSudwGWarze3wDuHwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAwBAgcMaLgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggg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AAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2Hvgrw34OTJk7J23To5depU3m/ClQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAo5A0Uhw2LZtu6xavVp27NwpRw4fkYRyCVK5UiU5r9m5UrRoRDQxEpj82pCSsk06duosBw4ekLKxsfLBogUSFxfnV4cdBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBnAuENZX6/IsvZdgjj8qW5OSgLS5apIh07nydjHxsuERHRwetc7oefGXOHCc00/ff98sv8uZbb0vvu/92unLw3ggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIDAHxYIW3D23Ky/y5MTJ2X5AifMVIRvzX1bvlrxlcx59WWpUrlylvVPp5OVAywqVaqY4fWnPT1Dkrdtc473ur2HNGxQP0MdDiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCKQLhCU4u/+BAfLu+wv9+iAhPk4a1K8v8Qnxsm7tBtm4aaNocKZFR6Rd0bqd/Gvum9KkcSO/607XnS43XC8rV62W5cuXS7s2baTDVe0zUMx5/XVJ3bPXOX7xhRcSnGUQ4gACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggg4BPI9+BsxVdf+4Vmuj7XszOny/nnNfO1ymwdSUuT4Y89LvPeme8c1xBt4OAhsnhB+r5f5dNwp0RMjIwf+/erY6MAAAArSURBVMRp+Oa8MgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDw5wj8P5sIjyCqFeV9AAAAAElFTkSuQmCC" + } + } + ], + "attachments": [ + { + "title": "License", + "filename": "attachments/019f49df-c3f9-4faf-81b1-decc13cc19da.ptart", + "data": "TUlUIExpY2Vuc2UKCkNvcHlyaWdodCAoYykgMjAxNyBQYXZhbiwgRmlzamthcnMsIE1pY2hlbGluIENFUlQKClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcwpmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgoKVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsCmNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgpJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUKU09GVFdBUkUuCg==" + } + ], + "references": [] + }, + { + "id": "PTART-2024-00003", + "title": "Unrated Hit", + "body": "Some hits are not rated.", + "remediation": "They can be informational or not related to a direct attack", + "asset": "https://test.example.com", + "severity": 5, + "fix_complexity": 3, + "cvss_vector": "", + "cvss_score": "", + "added": "2024-09-06T04:22:24.707", + "labels": [ + "A09:2021-Security Logging and Monitoring Failures" + ], + "screenshots": [], + "attachments": [], + "references": [] + } + ] + } + ], + "retests": [] +} \ No newline at end of file diff --git a/unittests/scans/ptart/ptart_one_vul.json b/unittests/scans/ptart/ptart_one_vul.json new file mode 100644 index 0000000000..67930bc339 --- /dev/null +++ b/unittests/scans/ptart/ptart_one_vul.json @@ -0,0 +1,71 @@ +{ + "name": "Test", + "executive_summary": "Mistakes were made", + "engagement_overview": "Things were done", + "conclusion": "Things should be put right", + "scope": "test.example.com", + "client": "Test Client", + "start_date": "2024-08-11", + "end_date": "2024-08-16", + "cvss_type": 3, + "tools": [ + "Burp Suite" + ], + "methodologies": [ + "OWASP Testing Guide V4.2" + ], + "pentesters": [ + { + "username": "hydragyrum", + "first_name": "", + "last_name": "" + } + ], + "assessments": [ + { + "title": "Test Assessment", + "hits": [ + { + "id": "PTART-2024-00002", + "title": "Broken Access Control", + "body": "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + "remediation": "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + "asset": "https://test.example.com", + "severity": 2, + "fix_complexity": 3, + "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + "cvss_score": "10.0", + "added": "2024-09-06T03:33:07.908", + "labels": [ + "A01:2021-Broken Access Control", + "A04:2021-Insecure Design" + ], + "screenshots": [ + { + "caption": "Borked", + "order": 0, + "screenshot": { + "filename": "screenshots/a78bebcc-6da7-4c25-86a3-441435ea68d0.png", + "data": "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AggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQCUUAAgbwtcOFErJyYv1jiFi+Tsxs35O2b5e58SiB/7ToS0byJFL21uQQXLeJTY2ewCCCAAAIIIIAAAggggAACCCCAAAIIIJA3BfwuqZQ3b427QgCB2MVL5fB3P8qFwwflYnKKXEpJAQUBrxHwCwwU/6BACY4uJdFPPCxFmjf1mrExEAQQQAABBBBAAAEEEEAAAQQQQAABBBC4PgWYcXZ9Pnfu+joQ0EGzQxMnSdLBGMlXoaJENGsiZR5/6Dq4c27RVwQOfP+TxC1ZJuf37DbeVT1ugme+8vQYJwIIIIAAAggggAACCCCAAAIIIIAAAnlTgMBZ3nyu3NV1LqCXZ9QzzXTQLKLJTVKswx0SXqnida7C7XubQFSH9lKgehU5Pn2GxC1bbryzBapWYdlGb3tQjAcBBBBAAAEEEEAAAQQQQAABBBBAAIHrSCBXAmcparm48+fPuzAHBQVJSEiIS3lWC1JTUyUxMdHldH9/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IYAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAII+KoAgTNffXKMGwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAwKMCBM48yklnCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACvipA4MxXnxzjRgABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQ8KgAgTOPctIZAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICArwoQOPPVJ8e4EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEPCpA4MyjnHSGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDgqwIEznz1yTFuBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABjwoQOPMoJ50hgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgj4qgCBM199cowbAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEDAowIEzjzKSWcIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAK+KkDgzFefHONGAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBDwqACBM49y0hkCCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggICvChA489Unx7gRQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQ8KkDgzKOcdIYAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIOCrAgTOfPXJMW4EEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAGPChA48ygnnSGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCPiqAIEzX31yjBsBBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQMCjAgTOPMpJZwgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAr4qQODMV58c40YAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEPCoAIEzj3LSGQIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgK8KEDjz1SfHuBFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBDwqQODMo5zZ39nadeuleu0bjU/Heztl/wW5AgIIIIAAAggggAACCCCAAAIIIIAAAggggAAC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kGcF0l9TMM/eNjeGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgKMAgTNHD44QQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSuUwECZ9fpg+e2EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEHAXyxB5njrfkfUfVqlaVO26/3RhYwwY3et8AGRECCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggID4XVIJBwQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSudwGWarze3wDuHwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAwBAgcMaLgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggg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AAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2Hvgrw34OTJk7J23To5depU3m/ClQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAo5A0Uhw2LZtu6xavVp27NwpRw4fkYRyCVK5UiU5r9m5UrRoRDQxEpj82pCSsk06duosBw4ekLKxsfLBogUSFxfnV4cdBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBnAuENZX6/IsvZdgjj8qW5OSgLS5apIh07nydjHxsuERHRwetc7oefGXOHCc00/ff98sv8uZbb0vvu/92unLw3ggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIDAHxYIW3D23Ky/y5MTJ2X5AifMVIRvzX1bvlrxlcx59WWpUrlylvVPp5OVAywqVaqY4fWnPT1Dkrdtc473ur2HNGxQP0MdDiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCKQLhCU4u/+BAfLu+wv9+iAhPk4a1K8v8Qnxsm7tBtm4aaNocKZFR6Rd0bqd/Gvum9KkcSO/607XnS43XC8rV62W5cuXS7s2baTDVe0zUMx5/XVJ3bPXOX7xhRcSnGUQ4gACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggg4BPI9+BsxVdf+4Vmuj7XszOny/nnNfO1ymwdSUuT4Y89LvPeme8c1xBt4OAhsnhB+r5f5dNwp0RMjIwf+/erY6MAAAArSURBVMRp+Oa8MgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDw5wj8P5sIjyCqFeV9AAAAAElFTkSuQmCC" + } + } + ], + "attachments": [ + { + "title": "License", + "filename": "attachments/019f49df-c3f9-4faf-81b1-decc13cc19da.ptart", + "data": "TUlUIExpY2Vuc2UKCkNvcHlyaWdodCAoYykgMjAxNyBQYXZhbiwgRmlzamthcnMsIE1pY2hlbGluIENFUlQKClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcwpmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgoKVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsCmNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgpJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUKU09GVFdBUkUuCg==" + } + ], + "references": [ + { + "name": "Reference", + "url": "https://ref.example.com" + } + ] + } + ] + } + ], + "retests": [] +} \ No newline at end of file diff --git a/unittests/scans/ptart/ptart_vuln_plus_retest.json b/unittests/scans/ptart/ptart_vuln_plus_retest.json new file mode 100644 index 0000000000..ad0f0dca0a --- /dev/null +++ b/unittests/scans/ptart/ptart_vuln_plus_retest.json @@ -0,0 +1,125 @@ +{ + "name": "Test", + "executive_summary": "Mistakes were made", + "engagement_overview": "Things were done", + "conclusion": "Things should be put right", + "scope": "test.example.com", + "client": "Test Client", + "start_date": "2024-08-11", + "end_date": "2024-08-16", + "cvss_type": 3, + "tools": [ + "Burp Suite" + ], + "methodologies": [ + "OWASP Testing Guide V4.2" + ], + "pentesters": [ + { + "username": "hydragyrum", + "first_name": "", + "last_name": "" + } + ], + "assessments": [ + { + "title": "Test Assessment", + "hits": [ + { + "id": "PTART-2024-00002", + "title": "Broken Access Control", + "body": "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + "remediation": "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + "asset": "https://test.example.com", + "severity": 2, + "fix_complexity": 3, + "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + "cvss_score": "10.0", + "added": "2024-09-06T03:33:07.908", + "labels": [ + "A01:2021-Broken Access Control", + "A04:2021-Insecure Design" + ], + "screenshots": [ + { + "caption": "Borked", + "order": 0, + "screenshot": { + "filename": "screenshots/a78bebcc-6da7-4c25-86a3-441435ea68d0.png", + "data": "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AggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQCUUAAgbwtcOFErJyYv1jiFi+Tsxs35O2b5e58SiB/7ToS0byJFL21uQQXLeJTY2ewCCCAAAIIIIAAAggggAACCCCAAAIIIJA3BfwuqZQ3b427QgCB2MVL5fB3P8qFwwflYnKKXEpJAQUBrxHwCwwU/6BACY4uJdFPPCxFmjf1mrExEAQQQAABBBBAAAEEEEAAAQQQQAABBBC4PgWYcXZ9Pnfu+joQ0EGzQxMnSdLBGMlXoaJENGsiZR5/6Dq4c27RVwQOfP+TxC1ZJuf37DbeVT1ugme+8vQYJwIIIIAAAggggAACCCCAAAIIIIAAAnlTgMBZ3nyu3NV1LqCXZ9QzzXTQLKLJTVKswx0SXqnida7C7XubQFSH9lKgehU5Pn2GxC1bbryzBapWYdlGb3tQjAcBBBBAAAEEEEAAAQQQQAABBBBAAIHrSCBXAmcparm48+fPuzAHBQVJSEiIS3lWC1JTUyUxMdHldH9/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IYAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAII+KoAgTNffXKMGwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAwKMCBM48yklnCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACvipA4MxXnxzjRgABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQ8KgAgTOPctIZAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICArwoQOPPVJ8e4EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEPCpA4MyjnHSGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDgqwIEznz1yTFuBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABjwoQOPMoJ50hgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgj4qgCBM199cowbAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEDAowIEzjzKSWcIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAK+KkDgzFefHONGAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBDwqACBM49y0hkCCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggICvChA489Unx7gRQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQ8KkDgzKOcdIYAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIOCrAgTOfPXJMW4EEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAGPChA48ygnnSGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCPiqAIEzX31yjBsBBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQMCjAgTOPMpJZwgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAr4qQODMV58c40YAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEPCoAIEzj3LSGQIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgK8KEDjz1SfHuBFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBDwqQODMo5zZ39nadeuleu0bjU/Heztl/wW5AgIIIIAAAggggAACCCCAAAIIIIAAAggggAAC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kGcF0l9TMM/eNjeGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgKMAgTNHD44QQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSuUwECZ9fpg+e2EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEHAXyxB5njrfkfUfVqlaVO26/3RhYwwY3et8AGRECCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggID4XVIJBwQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSudwGWarze3wDuHwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAwBAgcMaLgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggg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AAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2Hvgrw34OTJk7J23To5depU3m/ClQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAo5A0Uhw2LZtu6xavVp27NwpRw4fkYRyCVK5UiU5r9m5UrRoRDQxEpj82pCSsk06duosBw4ekLKxsfLBogUSFxfnV4cdBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBnAuENZX6/IsvZdgjj8qW5OSgLS5apIh07nydjHxsuERHRwetc7oefGXOHCc00/ff98sv8uZbb0vvu/92unLw3ggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIDAHxYIW3D23Ky/y5MTJ2X5AifMVIRvzX1bvlrxlcx59WWpUrlylvVPp5OVAywqVaqY4fWnPT1Dkrdtc473ur2HNGxQP0MdDiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCKQLhCU4u/+BAfLu+wv9+iAhPk4a1K8v8Qnxsm7tBtm4aaNocKZFR6Rd0bqd/Gvum9KkcSO/607XnS43XC8rV62W5cuXS7s2baTDVe0zUMx5/XVJ3bPXOX7xhRcSnGUQ4gACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggg4BPI9+BsxVdf+4Vmuj7XszOny/nnNfO1ymwdSUuT4Y89LvPeme8c1xBt4OAhsnhB+r5f5dNwp0RMjIwf+/erY6MAAAArSURBVMRp+Oa8MgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDw5wj8P5sIjyCqFeV9AAAAAElFTkSuQmCC" + } + } + ], + "attachments": [ + { + "title": "License", + "filename": "attachments/019f49df-c3f9-4faf-81b1-decc13cc19da.ptart", + "data": "TUlUIExpY2Vuc2UKCkNvcHlyaWdodCAoYykgMjAxNyBQYXZhbiwgRmlzamthcnMsIE1pY2hlbGluIENFUlQKClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcwpmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgoKVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsCmNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgpJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUKU09GVFdBUkUuCg==" + } + ], + "references": [] + }, + { + "id": "PTART-2024-00003", + "title": "Unrated Hit", + "body": "Some hits are not rated.", + "remediation": "They can be informational or not related to a direct attack", + "asset": "https://test.example.com", + "severity": 5, + "fix_complexity": 3, + "cvss_vector": "", + "cvss_score": "", + "added": "2024-09-06T04:22:24.707", + "labels": [ + "A09:2021-Security Logging and Monitoring Failures" + ], + "screenshots": [], + "attachments": [], + "references": [] + } + ] + } + ], + "retests": [ + { + "name": "Test Retest", + "introduction": "REEEEEEEEEEEEE-TEST!", + "conclusion": "Still broke, mate", + "start_date": "2024-09-08", + "end_date": "2024-09-13", + "hits": [ + { + "id": "PTART-2024-00002-RT", + "status": "NF", + "body": "Still borked", + "original_hit": { + "id": "PTART-2024-00002", + "title": "Broken Access Control", + "body": "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + "remediation": "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + "asset": "https://test.example.com", + "severity": 2, + "fix_complexity": 3, + "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + "cvss_score": "10.0", + "added": "2024-09-06T03:33:07.908", + "labels": [ + "A01:2021-Broken Access Control", + "A04:2021-Insecure Design" + ] + }, + "screenshots": [ + { + "caption": "Yet another Screenshot", + "order": 0, + "screenshot": { + "filename": "screenshots_retest/ea1c661f-7366-4619-a08b-133ec1a6cfd1.png", + "data": "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" + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/unittests/scans/ptart/ptart_vulns_with_mult_assessments.json b/unittests/scans/ptart/ptart_vulns_with_mult_assessments.json new file mode 100644 index 0000000000..1ad9d01d1f --- /dev/null +++ b/unittests/scans/ptart/ptart_vulns_with_mult_assessments.json @@ -0,0 +1,107 @@ +{ + "name": "Test", + "executive_summary": "Mistakes were made", + "engagement_overview": "Things were done", + "conclusion": "Things should be put right", + "scope": "test.example.com", + "client": "Test Client", + "start_date": "2024-08-11", + "end_date": "2024-08-16", + "cvss_type": 3, + "tools": [ + "Burp Suite" + ], + "methodologies": [ + "OWASP Testing Guide V4.2" + ], + "pentesters": [ + { + "username": "hydragyrum", + "first_name": "", + "last_name": "" + } + ], + "assessments": [ + { + "title": "New API", + "hits": [ + { + "id": "PTART-2024-00004", + "title": "HTML Injection", + "body": "HTML injection is a type of injection issue that occurs when a user is able to control an input point and is able to inject arbitrary HTML code into a vulnerable web page. This vulnerability can have many consequences, like disclosure of a user's session cookies that could be used to impersonate the victim, or, more generally, it can allow the attacker to modify the page content seen by the victims.", + "remediation": "Preventing HTML injection is trivial in some cases but can be much harder depending on the complexity of the application and the ways it handles user-controllable data.\n\nIn general, effectively preventing HTML injection vulnerabilities is likely to involve a combination of the following measures:\n\n* **Filter input on arrival**. At the point where user input is received, filter as strictly as possible based on what is expected or valid input.\n* **Encode data on output**. At the point where user-controllable data is output in HTTP responses, encode the output to prevent it from being interpreted as active content. Depending on the output context, this might require applying combinations of HTML, URL, JavaScript, and CSS encoding.", + "asset": "", + "severity": 4, + "fix_complexity": 2, + "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N", + "cvss_score": "8.2", + "added": "2024-09-06T09:47:16.944", + "labels": [ + "A03:2021-Injection" + ], + "screenshots": [], + "attachments": [], + "references": [] + } + ] + }, + { + "title": "Test Assessment", + "hits": [ + { + "id": "PTART-2024-00002", + "title": "Broken Access Control", + "body": "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + "remediation": "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + "asset": "https://test.example.com", + "severity": 2, + "fix_complexity": 3, + "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + "cvss_score": "10.0", + "added": "2024-09-06T03:33:07.908", + "labels": [ + "A01:2021-Broken Access Control", + "A04:2021-Insecure Design" + ], + "screenshots": [ + { + "caption": "Borked", + "order": 0, + "screenshot": { + "filename": "screenshots/a78bebcc-6da7-4c25-86a3-441435ea68d0.png", + "data": "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AggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQInPEaIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIKAECJzxGiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCgBAic8RoggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggoAQCUUAAgbwtcOFErJyYv1jiFi+Tsxs35O2b5e58SiB/7ToS0byJFL21uQQXLeJTY2ewCCCAAAIIIIAAAggggAACCCCAAAIIIJA3BfwuqZQ3b427QgCB2MVL5fB3P8qFwwflYnKKXEpJAQUBrxHwCwwU/6BACY4uJdFPPCxFmjf1mrExEAQQQAABBBBAAAEEEEAAAQQQQAABBBC4PgWYcXZ9Pnfu+joQ0EGzQxMnSdLBGMlXoaJENGsiZR5/6Dq4c27RVwQOfP+TxC1ZJuf37DbeVT1ugme+8vQYJwIIIIAAAggggAACCCCAAAIIIIAAAnlTgMBZ3nyu3NV1LqCXZ9QzzXTQLKLJTVKswx0SXqnida7C7XubQFSH9lKgehU5Pn2GxC1bbryzBapWYdlGb3tQjAcBBBBAAAEEEEAAAQQQQAABBBBAAIHrSCBXAmcparm48+fPuzAHBQVJSEiIS3lWC1JTUyUxMdHldH9/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IYAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAII+KoAgTNffXKMGwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAwKMCBM48yklnCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACvipA4MxXnxzjRgABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQ8KgAgTOPctIZAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICArwoQOPPVJ8e4EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEPCpA4MyjnHSGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDgqwIEznz1yTFuBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABjwoQOPMoJ50hgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgj4qgCBM199cowbAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEDAowIEzjzKSWcIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAK+KkDgzFefHONGAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBDwqACBM49y0hkCCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggICvChA489Unx7gRQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQ8KkDgzKOcdIYAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIOCrAgTOfPXJMW4EEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAGPChA48ygnnSGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCPiqAIEzX31yjBsBBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQMCjAgTOPMpJZwgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAr4qQODMV58c40YAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEPCoAIEzj3LSGQIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgK8KEDjz1SfHuBFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBDwqQODMo5zZ39nadeuleu0bjU/Heztl/wW5AgIIIIAAAggggAACCCCAAAIIIIAAAggggAAC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kGcF0l9TMM/eNjeGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgKMAgTNHD44QQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSuUwECZ9fpg+e2EUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEHAXyxB5njrfkfUfVqlaVO26/3RhYwwY3et8AGRECCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggID4XVIJBwQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSudwGWarze3wDuHwEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAwBAgcMaLgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAgBIgcMZrgAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggIASIHDGa4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIICAEiBwxmuAAAIIIIAAAggg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AAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2HvAhqAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQCQIEZ5HQC7QBAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAg7AIEZ2Hvgrw34OTJk7J23To5depU3m/ClQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAo5A0Uhw2LZtu6xavVp27NwpRw4fkYRyCVK5UiU5r9m5UrRoRDQxEpj82pCSsk06duosBw4ekLKxsfLBogUSFxfnV4cdBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBnAuENZX6/IsvZdgjj8qW5OSgLS5apIh07nydjHxsuERHRwetc7oefGXOHCc00/ff98sv8uZbb0vvu/92unLw3ggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIDAHxYIW3D23Ky/y5MTJ2X5AifMVIRvzX1bvlrxlcx59WWpUrlylvVPp5OVAywqVaqY4fWnPT1Dkrdtc473ur2HNGxQP0MdDiCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCKQLhCU4u/+BAfLu+wv9+iAhPk4a1K8v8Qnxsm7tBtm4aaNocKZFR6Rd0bqd/Gvum9KkcSO/607XnS43XC8rV62W5cuXS7s2baTDVe0zUMx5/XVJ3bPXOX7xhRcSnGUQ4gACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggg4BPI9+BsxVdf+4Vmuj7XszOny/nnNfO1ymwdSUuT4Y89LvPeme8c1xBt4OAhsnhB+r5f5dNwp0RMjIwf+/erY6MAAAArSURBVMRp+Oa8MgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCDw5wj8P5sIjyCqFeV9AAAAAElFTkSuQmCC" + } + } + ], + "attachments": [ + { + "title": "License", + "filename": "attachments/019f49df-c3f9-4faf-81b1-decc13cc19da.ptart", + "data": "TUlUIExpY2Vuc2UKCkNvcHlyaWdodCAoYykgMjAxNyBQYXZhbiwgRmlzamthcnMsIE1pY2hlbGluIENFUlQKClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcwpmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgoKVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsCmNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgpJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUKU09GVFdBUkUuCg==" + } + ], + "references": [] + }, + { + "id": "PTART-2024-00003", + "title": "Unrated Hit", + "body": "Some hits are not rated.", + "remediation": "They can be informational or not related to a direct attack", + "asset": "https://test.example.com", + "severity": 5, + "fix_complexity": 3, + "cvss_vector": "", + "cvss_score": "", + "added": "2024-09-06T04:22:24.707", + "labels": [ + "A09:2021-Security Logging and Monitoring Failures" + ], + "screenshots": [], + "attachments": [], + "references": [] + } + ] + } + ], + "retests": [] +} \ No newline at end of file diff --git a/unittests/scans/ptart/ptart_zero_vul.json b/unittests/scans/ptart/ptart_zero_vul.json new file mode 100644 index 0000000000..bfdf77d03a --- /dev/null +++ b/unittests/scans/ptart/ptart_zero_vul.json @@ -0,0 +1,26 @@ +{ + "name": "Test", + "executive_summary": "Mistakes were made", + "engagement_overview": "Things were done", + "conclusion": "Things should be put right", + "scope": "test.example.com", + "client": "Test Client", + "start_date": "2024-08-11", + "end_date": "2024-08-16", + "cvss_type": 3, + "tools": [ + "Burp Suite" + ], + "methodologies": [ + "OWASP Testing Guide V4.2" + ], + "pentesters": [ + { + "username": "hydragyrum", + "first_name": "", + "last_name": "" + } + ], + "assessments": [], + "retests": [] +} \ No newline at end of file diff --git a/unittests/tools/test_ptart_parser.py b/unittests/tools/test_ptart_parser.py new file mode 100644 index 0000000000..83be6417b3 --- /dev/null +++ b/unittests/tools/test_ptart_parser.py @@ -0,0 +1,694 @@ +from django.test import TestCase + +from dojo.models import Engagement, Product, Test +from dojo.tools.ptart.parser import PTARTParser + + +class TestPTARTParser(TestCase): + + def setUp(self): + self.product = Product(name="sample product", + description="what a description") + self.engagement = Engagement(name="sample engagement", + product=self.product) + self.test = Test(engagement=self.engagement) + + def test_ptart_parser_tools_parse_ptart_severity(self): + from dojo.tools.ptart.ptart_parser_tools import parse_ptart_severity + with self.subTest("Critical"): + self.assertEqual("Critical", parse_ptart_severity(1)) + with self.subTest("High"): + self.assertEqual("High", parse_ptart_severity(2)) + with self.subTest("Medium"): + self.assertEqual("Medium", parse_ptart_severity(3)) + with self.subTest("Low"): + self.assertEqual("Low", parse_ptart_severity(4)) + with self.subTest("Info"): + self.assertEqual("Info", parse_ptart_severity(5)) + with self.subTest("Unknown"): + self.assertEqual("Info", parse_ptart_severity(6)) + + def test_ptart_parser_tools_parse_ptart_fix_effort(self): + from dojo.tools.ptart.ptart_parser_tools import parse_ptart_fix_effort + with self.subTest("High"): + self.assertEqual("High", parse_ptart_fix_effort(1)) + with self.subTest("Medium"): + self.assertEqual("Medium", parse_ptart_fix_effort(2)) + with self.subTest("Low"): + self.assertEqual("Low", parse_ptart_fix_effort(3)) + with self.subTest("Unknown"): + self.assertEqual(None, parse_ptart_fix_effort(4)) + + def test_ptart_parser_tools_parse_title_from_hit(self): + from dojo.tools.ptart.ptart_parser_tools import parse_title_from_hit + with self.subTest("Title and ID"): + self.assertEqual("1234: Test Title", parse_title_from_hit({"title": "Test Title", "id": "1234"})) + with self.subTest("Title Only"): + self.assertEqual("Test Title", parse_title_from_hit({"title": "Test Title"})) + with self.subTest("ID Only"): + self.assertEqual("1234", parse_title_from_hit({"id": "1234"})) + with self.subTest("No Title or ID"): + self.assertEqual("Unknown Hit", parse_title_from_hit({})) + with self.subTest("Empty Title"): + self.assertEqual("Unknown Hit", parse_title_from_hit({"title": ""})) + with self.subTest("Empty ID"): + self.assertEqual("Unknown Hit", parse_title_from_hit({"id": ""})) + with self.subTest("Blank Title and Blank ID"): + self.assertEqual("Unknown Hit", parse_title_from_hit({"title": "", "id": ""})) + with self.subTest("Blank Title and Non-blank id"): + self.assertEqual("1234", parse_title_from_hit({"title": "", "id": "1234"})) + with self.subTest("Non-blank Title and Blank id"): + self.assertEqual("Test Title", parse_title_from_hit({"title": "Test Title", "id": ""})) + + def test_ptart_parser_tools_cvss_vector_acquisition(self): + from dojo.tools.ptart.ptart_parser_tools import parse_cvss_vector + with self.subTest("Test CVSSv3 Vector"): + hit = { + "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + } + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", parse_cvss_vector(hit, 3)) + with self.subTest("Test CVSSv4 Vector"): + hit = { + "cvss_vector": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:N/SI:N/SA:N", + } + self.assertEqual(None, parse_cvss_vector(hit, 4)) + with self.subTest("Test CVSSv3 Vector with CVSSv4 Request"): + hit = { + "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + } + self.assertEqual(None, parse_cvss_vector(hit, 4)) + with self.subTest("Test CVSSv4 Vector with CVSSv3 Request"): + hit = { + "cvss_vector": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:N/SI:N/SA:N", + } + self.assertEqual(None, parse_cvss_vector(hit, 3)) + with self.subTest("Test No CVSS Vector"): + hit = {} + self.assertEqual(None, parse_cvss_vector(hit, 3)) + with self.subTest("Test CVSSv2 Vector"): + hit = { + "cvss_vector": "CVSS:2.0/AV:N/AC:L/Au:N/C:C/I:C/A:C", + } + self.assertEqual(None, parse_cvss_vector(hit, 2)) + with self.subTest("Test Blank CVSS Vector"): + hit = { + "cvss_vector": "", + } + self.assertEqual(None, parse_cvss_vector(hit, 3)) + + def test_ptart_parser_tools_retest_fix_status_parse(self): + from dojo.tools.ptart.ptart_parser_tools import parse_retest_status + with self.subTest("Fixed"): + self.assertEqual("Fixed", parse_retest_status("F")) + with self.subTest("Not Fixed"): + self.assertEqual("Not Fixed", parse_retest_status("NF")) + with self.subTest("Partially Fixed"): + self.assertEqual("Partially Fixed", parse_retest_status("PF")) + with self.subTest("Not Applicable"): + self.assertEqual("Not Applicable", parse_retest_status("NA")) + with self.subTest("Not Tested"): + self.assertEqual("Not Tested", parse_retest_status("NT")) + with self.subTest("Unknown"): + self.assertEqual(None, parse_retest_status("U")) + with self.subTest("Empty"): + self.assertEqual(None, parse_retest_status("")) + + def test_ptart_parser_tools_parse_screenshots_from_hit(self): + from dojo.tools.ptart.ptart_parser_tools import parse_screenshots_from_hit + with self.subTest("No Screenshots"): + hit = {} + screenshots = parse_screenshots_from_hit(hit) + self.assertEqual([], screenshots) + with self.subTest("One Screenshot"): + hit = { + "screenshots": [{ + "caption": "One", + "order": 0, + "screenshot": { + "filename": "screenshots/a78bebcc-6da7-4c25-86a3-441435ea68d0.png", + "data": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + }, + }], + } + screenshots = parse_screenshots_from_hit(hit) + self.assertEqual(1, len(screenshots)) + screenshot = screenshots[0] + self.assertEqual("One.png", screenshot["title"]) + self.assertTrue(screenshot["data"] == "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + "Invalid Screenshot Data") + with self.subTest("Two Screenshots"): + hit = { + "screenshots": [{ + "caption": "One", + "order": 0, + "screenshot": { + "filename": "screenshots/a78bebcc-6da7-4c25-86a3-441435ea68d0.png", + "data": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + }, + }, { + "caption": "Two", + "order": 1, + "screenshot": { + "filename": "screenshots/123e4567-e89b-12d3-a456-426614174000.png", + "data": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + }, + }], + } + screenshots = parse_screenshots_from_hit(hit) + self.assertEqual(2, len(screenshots)) + first_screenshot = screenshots[0] + self.assertEqual("One.png", first_screenshot["title"]) + self.assertTrue(first_screenshot["data"] == "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + "Invalid Screenshot Data") + second_screenshot = screenshots[1] + self.assertEqual("Two.png", second_screenshot["title"]) + self.assertTrue(second_screenshot["data"] == "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + "Invalid Screenshot Data") + with self.subTest("Empty Screenshot"): + hit = { + "screenshots": [{ + "caption": "Borked", + "order": 0, + "screenshot": { + "filename": "screenshots/a78bebcc-6da7-4c25-86a3-441435ea68d0.png", + "data": "", + }, + }], + } + screenshots = parse_screenshots_from_hit(hit) + self.assertEqual(0, len(screenshots)) + with self.subTest("Screenshot with No Caption"): + hit = { + "screenshots": [{ + "order": 0, + "screenshot": { + "filename": "screenshots/a78bebcc-6da7-4c25-86a3-441435ea68d0.png", + "data": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + }, + }], + } + screenshots = parse_screenshots_from_hit(hit) + self.assertEqual(1, len(screenshots)) + screenshot = screenshots[0] + self.assertEqual("screenshot.png", screenshot["title"]) + self.assertTrue(screenshot["data"] == "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + "Invalid Screenshot Data") + with self.subTest("Screenshot with Blank Caption"): + hit = { + "screenshots": [{ + "caption": "", + "order": 0, + "screenshot": { + "filename": "screenshots/a78bebcc-6da7-4c25-86a3-441435ea68d0.png", + "data": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + }, + }], + } + screenshots = parse_screenshots_from_hit(hit) + self.assertEqual(1, len(screenshots)) + screenshot = screenshots[0] + self.assertEqual("screenshot.png", screenshot["title"]) + self.assertTrue(screenshot["data"] == "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABzElEQVR42mNk", + "Invalid Screenshot Data") + + def test_ptart_parser_tools_parse_attachment_from_hit(self): + from dojo.tools.ptart.ptart_parser_tools import parse_attachment_from_hit + with self.subTest("No Attachments"): + hit = {} + attachments = parse_attachment_from_hit(hit) + self.assertEqual([], attachments) + with self.subTest("One Attachment"): + hit = { + "attachments": [{ + "title": "License", + "data": "TUlUIExpY2Vuc2UKCkNvcHl", + }], + } + attachments = parse_attachment_from_hit(hit) + self.assertEqual(1, len(attachments)) + attachment = attachments[0] + self.assertEqual("License", attachment["title"]) + self.assertTrue(attachment["data"] == "TUlUIExpY2Vuc2UKCkNvcHl", "Invalid Attachment Data") + with self.subTest("Two Attachments"): + hit = { + "attachments": [{ + "title": "License", + "data": "TUlUIExpY2Vuc2UKCkNvcHl", + }, { + "title": "Readme", + "data": "UkVBRERtZQoK", + }], + } + attachments = parse_attachment_from_hit(hit) + self.assertEqual(2, len(attachments)) + first_attachment = attachments[0] + self.assertEqual("License", first_attachment["title"]) + self.assertTrue(first_attachment["data"] == "TUlUIExpY2Vuc2UKCkNvcHl", "Invalid Attachment Data") + second_attachment = attachments[1] + self.assertEqual("Readme", second_attachment["title"]) + self.assertTrue(second_attachment["data"] == "UkVBRERtZQoK", "Invalid Attachment Data") + with self.subTest("Empty Attachment"): + hit = { + "attachments": [{ + "title": "License", + "data": "", + }], + } + attachments = parse_attachment_from_hit(hit) + self.assertEqual(0, len(attachments)) + with self.subTest("No Data Attachment"): + hit = { + "attachments": [{ + "title": "License", + }], + } + attachments = parse_attachment_from_hit(hit) + self.assertEqual(0, len(attachments)) + with self.subTest("Attachement with no Title"): + hit = { + "attachments": [{ + "data": "TUlUIExpY2Vuc2UKCkNvcHl", + }], + } + attachments = parse_attachment_from_hit(hit) + self.assertEqual(1, len(attachments)) + attachment = attachments[0] + self.assertEqual("attachment", attachment["title"]) + self.assertTrue(attachment["data"] == "TUlUIExpY2Vuc2UKCkNvcHl", "Invalid Attachment Data") + with self.subTest("Attachment with Blank Title"): + hit = { + "attachments": [{ + "title": "", + "data": "TUlUIExpY2Vuc2UKCkNvcHl", + }], + } + attachments = parse_attachment_from_hit(hit) + self.assertEqual(1, len(attachments)) + attachment = attachments[0] + self.assertEqual("attachment", attachment["title"]) + + self.assertTrue(attachment["data"] == "TUlUIExpY2Vuc2UKCkNvcHl", "Invalid Attachment Data") + + def test_ptart_parser_tools_get_description_from_report_base(self): + from dojo.tools.ptart.ptart_parser_tools import generate_test_description_from_report + with self.subTest("No Description"): + data = {} + self.assertEqual(None, generate_test_description_from_report(data)) + with self.subTest("Description from Executive Summary Only"): + data = { + "executive_summary": "This is a summary", + } + self.assertEqual("This is a summary", generate_test_description_from_report(data)) + with self.subTest("Description from Engagement Overview Only"): + data = { + "engagement_overview": "This is an overview", + } + self.assertEqual("This is an overview", generate_test_description_from_report(data)) + with self.subTest("Description from Conclusion Only"): + data = { + "conclusion": "This is a conclusion", + } + self.assertEqual("This is a conclusion", generate_test_description_from_report(data)) + with self.subTest("Description from All Sections"): + data = { + "executive_summary": "This is a summary", + "engagement_overview": "This is an overview", + "conclusion": "This is a conclusion", + } + self.assertEqual("This is a summary\n\nThis is an overview\n\nThis is a conclusion", + generate_test_description_from_report(data)) + with self.subTest("Description from Executive Summary and Conclusion"): + data = { + "executive_summary": "This is a summary", + "conclusion": "This is a conclusion", + } + self.assertEqual("This is a summary\n\nThis is a conclusion", + generate_test_description_from_report(data)) + with self.subTest("Description from Executive Summary and Engagement Overview"): + data = { + "executive_summary": "This is a summary", + "engagement_overview": "This is an overview", + } + self.assertEqual("This is a summary\n\nThis is an overview", + generate_test_description_from_report(data)) + with self.subTest("Description from Engagement Overview and Conclusion"): + data = { + "engagement_overview": "This is an overview", + "conclusion": "This is a conclusion", + } + self.assertEqual("This is an overview\n\nThis is a conclusion", + generate_test_description_from_report(data)) + with self.subTest("Description from All Sections with Empty Strings"): + data = { + "executive_summary": "", + "engagement_overview": "", + "conclusion": "", + } + self.assertEqual(None, generate_test_description_from_report(data)) + with self.subTest("Description with Some Blank Strings"): + data = { + "executive_summary": "", + "engagement_overview": "This is an overview", + "conclusion": "", + } + self.assertEqual("This is an overview", generate_test_description_from_report(data)) + + def test_ptart_parser_tools_parse_references_from_hit(self): + from dojo.tools.ptart.ptart_parser_tools import parse_references_from_hit + with self.subTest("No References"): + hit = {} + self.assertEqual(None, parse_references_from_hit(hit)) + with self.subTest("One Reference"): + hit = { + "references": [{ + "name": "Reference", + "url": "https://ref.example.com", + }], + } + self.assertEqual("Reference: https://ref.example.com", parse_references_from_hit(hit)) + with self.subTest("Two References"): + hit = { + "references": [{ + "name": "Reference1", + "url": "https://ref.example.com", + }, { + "name": "Reference2", + "url": "https://ref2.example.com", + }], + } + self.assertEqual("Reference1: https://ref.example.com\nReference2: https://ref2.example.com", + parse_references_from_hit(hit)) + with self.subTest("No Data Reference"): + hit = { + "references": [], + } + self.assertEqual(None, parse_references_from_hit(hit)) + with self.subTest("Reference with No Name"): + hit = { + "references": [{ + "url": "https://ref.example.com", + }], + } + self.assertEqual("Reference: https://ref.example.com", parse_references_from_hit(hit)) + with self.subTest("Reference with No URL"): + hit = { + "references": [{ + "name": "Reference", + }], + } + self.assertEqual(None, parse_references_from_hit(hit)) + with self.subTest("Mixed bag of valid and invalid references"): + hit = { + "references": [{ + "name": "Reference1", + "url": "https://ref.example.com", + }, { + "name": "Reference2", + }, { + "url": "https://ref3.example.com", + }], + } + self.assertEqual("Reference1: https://ref.example.com\nReference: https://ref3.example.com", parse_references_from_hit(hit)) + + def test_ptart_parser_with_empty_json_throws_error(self): + with open("unittests/scans/ptart/empty_with_error.json", encoding="utf-8") as testfile: + parser = PTARTParser() + findings = parser.get_findings(testfile, self.test) + self.assertEqual(0, len(findings)) + + def test_ptart_parser_with_no_assessments_has_no_findings(self): + with open("unittests/scans/ptart/ptart_zero_vul.json", encoding="utf-8") as testfile: + parser = PTARTParser() + findings = parser.get_findings(testfile, self.test) + self.assertEqual(0, len(findings)) + + def test_ptart_parser_with_one_assessment_has_one_finding(self): + with open("unittests/scans/ptart/ptart_one_vul.json", encoding="utf-8") as testfile: + parser = PTARTParser() + findings = parser.get_findings(testfile, self.test) + self.assertEqual(1, len(findings)) + with self.subTest("Test Assessment: Broken Access Control"): + finding = findings[0] + self.assertEqual("PTART-2024-00002: Broken Access Control", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual( + "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + finding.description) + self.assertEqual( + "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + finding.mitigation) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) + self.assertEqual("PTART-2024-00002", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.cve) + self.assertEqual("Low", finding.effort_for_fixing) + self.assertEqual("Test Assessment", finding.component_name) + self.assertEqual("2024-09-06", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(2, len(finding.unsaved_tags)) + self.assertEqual([ + "A01:2021-Broken Access Control", + "A04:2021-Insecure Design", + ], finding.unsaved_tags) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "https://test.example.com") + self.assertEqual(2, len(finding.unsaved_files)) + screenshot = finding.unsaved_files[0] + self.assertEqual("Borked.png", screenshot["title"]) + self.assertTrue(screenshot["data"].startswith("iVBORw0KGgoAAAAN"), "Invalid Screenshot Data") + attachment = finding.unsaved_files[1] + self.assertEqual("License", attachment["title"]) + self.assertTrue(attachment["data"].startswith("TUlUIExpY2Vuc2UKCkNvcHl"), "Invalid Attachment Data") + self.assertEqual("Reference: https://ref.example.com", finding.references) + + def test_ptart_parser_with_one_assessment_has_many_findings(self): + with open("unittests/scans/ptart/ptart_many_vul.json", encoding="utf-8") as testfile: + parser = PTARTParser() + findings = parser.get_findings(testfile, self.test) + self.assertEqual(2, len(findings)) + with self.subTest("Test Assessment: Broken Access Control"): + finding = findings[0] + self.assertEqual("PTART-2024-00002: Broken Access Control", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual( + "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + finding.description) + self.assertEqual( + "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + finding.mitigation) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) + self.assertEqual("PTART-2024-00002", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.cve) + self.assertEqual("Low", finding.effort_for_fixing) + self.assertEqual("Test Assessment", finding.component_name) + self.assertEqual("2024-09-06", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "https://test.example.com") + self.assertEqual(2, len(finding.unsaved_files)) + screenshot = finding.unsaved_files[0] + self.assertEqual("Borked.png", screenshot["title"]) + self.assertTrue(screenshot["data"].startswith("iVBORw0KGgoAAAAN"), "Invalid Screenshot Data") + attachment = finding.unsaved_files[1] + self.assertEqual("License", attachment["title"]) + self.assertTrue(attachment["data"].startswith("TUlUIExpY2Vuc2UKCkNvcHl"), "Invalid Attachment Data") + self.assertEqual(None, finding.references) + with self.subTest("Test Assessment: Unrated Hit"): + finding = findings[1] + self.assertEqual("PTART-2024-00003: Unrated Hit", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual("Some hits are not rated.", finding.description) + self.assertEqual("They can be informational or not related to a direct attack", finding.mitigation) + self.assertEqual(None, finding.cvssv3) + self.assertEqual("PTART-2024-00003", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00003", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00003", finding.cve) + self.assertEqual("Low", finding.effort_for_fixing) + self.assertEqual("Test Assessment", finding.component_name) + self.assertEqual("2024-09-06", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(None, finding.references) + + def test_ptart_parser_with_multiple_assessments_has_many_findings_correctly_grouped(self): + with open("unittests/scans/ptart/ptart_vulns_with_mult_assessments.json", encoding="utf-8") as testfile: + parser = PTARTParser() + findings = parser.get_findings(testfile, self.test) + self.assertEqual(3, len(findings)) + with self.subTest("Test Assessment: Broken Access Control"): + finding = next((f for f in findings if f.unique_id_from_tool == "PTART-2024-00002"), None) + self.assertEqual("PTART-2024-00002: Broken Access Control", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual( + "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + finding.description) + self.assertEqual( + "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + finding.mitigation) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) + self.assertEqual("PTART-2024-00002", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.cve) + self.assertEqual("Low", finding.effort_for_fixing) + self.assertEqual("Test Assessment", finding.component_name) + self.assertEqual("2024-09-06", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "https://test.example.com") + self.assertEqual(2, len(finding.unsaved_files)) + screenshot = finding.unsaved_files[0] + self.assertEqual("Borked.png", screenshot["title"]) + self.assertTrue(screenshot["data"].startswith("iVBORw0KGgoAAAAN"), "Invalid Screenshot Data") + attachment = finding.unsaved_files[1] + self.assertEqual("License", attachment["title"]) + self.assertTrue(attachment["data"].startswith("TUlUIExpY2Vuc2UKCkNvcHl"), "Invalid Attachment Data") + self.assertEqual(None, finding.references) + with self.subTest("Test Assessment: Unrated Hit"): + finding = next((f for f in findings if f.unique_id_from_tool == "PTART-2024-00003"), None) + self.assertEqual("PTART-2024-00003: Unrated Hit", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual("Some hits are not rated.", finding.description) + self.assertEqual("They can be informational or not related to a direct attack", finding.mitigation) + self.assertEqual(None, finding.cvssv3) + self.assertEqual("PTART-2024-00003", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00003", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00003", finding.cve) + self.assertEqual("Low", finding.effort_for_fixing) + self.assertEqual("Test Assessment", finding.component_name) + self.assertEqual("2024-09-06", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(None, finding.references) + with self.subTest("New Api: HTML Injection"): + finding = next((f for f in findings if f.unique_id_from_tool == "PTART-2024-00004"), None) + self.assertEqual("PTART-2024-00004: HTML Injection", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual( + "HTML injection is a type of injection issue that occurs when a user is able to control an input point and is able to inject arbitrary HTML code into a vulnerable web page. This vulnerability can have many consequences, like disclosure of a user's session cookies that could be used to impersonate the victim, or, more generally, it can allow the attacker to modify the page content seen by the victims.", + finding.description) + self.assertEqual( + "Preventing HTML injection is trivial in some cases but can be much harder depending on the complexity of the application and the ways it handles user-controllable data.\n\nIn general, effectively preventing HTML injection vulnerabilities is likely to involve a combination of the following measures:\n\n* **Filter input on arrival**. At the point where user input is received, filter as strictly as possible based on what is expected or valid input.\n* **Encode data on output**. At the point where user-controllable data is output in HTTP responses, encode the output to prevent it from being interpreted as active content. Depending on the output context, this might require applying combinations of HTML, URL, JavaScript, and CSS encoding.", + finding.mitigation) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N", finding.cvssv3) + self.assertEqual("PTART-2024-00004", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00004", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00004", finding.cve) + self.assertEqual("Medium", finding.effort_for_fixing) + self.assertEqual("New API", finding.component_name) + self.assertEqual("2024-09-06", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(0, len(finding.unsaved_endpoints)) + self.assertEqual(0, len(finding.unsaved_files)) + self.assertEqual(None, finding.references) + + def test_ptart_parser_with_single_vuln_on_import_test(self): + with open("unittests/scans/ptart/ptart_one_vul.json", encoding="utf-8") as testfile: + parser = PTARTParser() + tests = parser.get_tests("PTART Report", testfile) + self.assertEqual(1, len(tests)) + test = tests[0] + self.assertEqual("Test Report", test.name) + self.assertEqual("Test Report", test.type) + self.assertEqual("", test.version) + self.assertEqual("Mistakes were made\n\nThings were done\n\nThings should be put right", test.description) + self.assertEqual("2024-08-11", test.target_start.strftime("%Y-%m-%d")) + self.assertEqual("2024-08-16", test.target_end.strftime("%Y-%m-%d")) + self.assertEqual(1, len(test.findings)) + finding = test.findings[0] + self.assertEqual("PTART-2024-00002: Broken Access Control", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual( + "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + finding.description) + self.assertEqual( + "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + finding.mitigation) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) + self.assertEqual("PTART-2024-00002", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.cve) + self.assertEqual("Low", finding.effort_for_fixing) + self.assertEqual("Test Assessment", finding.component_name) + self.assertEqual("2024-09-06", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(2, len(finding.unsaved_tags)) + self.assertEqual([ + "A01:2021-Broken Access Control", + "A04:2021-Insecure Design", + ], finding.unsaved_tags) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "https://test.example.com") + self.assertEqual(2, len(finding.unsaved_files)) + screenshot = finding.unsaved_files[0] + self.assertEqual("Borked.png", screenshot["title"]) + self.assertTrue(screenshot["data"].startswith("iVBORw0KGgoAAAAN"), "Invalid Screenshot Data") + attachment = finding.unsaved_files[1] + self.assertEqual("License", attachment["title"]) + self.assertTrue(attachment["data"].startswith("TUlUIExpY2Vuc2UKCkNvcHl"), "Invalid Attachment Data") + self.assertEqual("Reference: https://ref.example.com", finding.references) + + def test_ptart_parser_with_retest_campaign(self): + with open("unittests/scans/ptart/ptart_vuln_plus_retest.json", encoding="utf-8") as testfile: + parser = PTARTParser() + findings = parser.get_findings(testfile, self.test) + self.assertEqual(3, len(findings)) + with self.subTest("Test Assessment: Broken Access Control"): + finding = next((f for f in findings if f.unique_id_from_tool == "PTART-2024-00002"), None) + self.assertEqual("PTART-2024-00002: Broken Access Control", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual( + "Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification or destruction of all data, or performing a business function outside of the limits of the user.", + finding.description) + self.assertEqual( + "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + finding.mitigation) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) + self.assertEqual("PTART-2024-00002", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.cve) + self.assertEqual("Low", finding.effort_for_fixing) + self.assertEqual("Test Assessment", finding.component_name) + self.assertEqual("2024-09-06", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "https://test.example.com") + self.assertEqual(2, len(finding.unsaved_files)) + screenshot = finding.unsaved_files[0] + self.assertEqual("Borked.png", screenshot["title"]) + self.assertTrue(screenshot["data"].startswith("iVBORw0KGgoAAAAN"), "Invalid Screenshot Data") + attachment = finding.unsaved_files[1] + self.assertEqual("License", attachment["title"]) + self.assertTrue(attachment["data"].startswith("TUlUIExpY2Vuc2UKCkNvcHl"), "Invalid Attachment Data") + self.assertEqual(None, finding.references) + with self.subTest("Test Assessment: Unrated Hit"): + finding = next((f for f in findings if f.unique_id_from_tool == "PTART-2024-00003"), None) + self.assertEqual("PTART-2024-00003: Unrated Hit", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual("Some hits are not rated.", finding.description) + self.assertEqual("They can be informational or not related to a direct attack", finding.mitigation) + self.assertEqual(None, finding.cvssv3) + self.assertEqual("PTART-2024-00003", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00003", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00003", finding.cve) + self.assertEqual("Low", finding.effort_for_fixing) + self.assertEqual("Test Assessment", finding.component_name) + self.assertEqual("2024-09-06", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(None, finding.references) + with self.subTest("Retest: Broken Access Control"): + finding = next((f for f in findings if f.unique_id_from_tool == "PTART-2024-00002-RT"), None) + self.assertEqual("PTART-2024-00002-RT: Broken Access Control (Not Fixed)", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual("Still borked", finding.description) + self.assertEqual( + "Access control vulnerabilities can generally be prevented by taking a defense-in-depth approach and applying the following principles:\n\n* Never rely on obfuscation alone for access control.\n* Unless a resource is intended to be publicly accessible, deny access by default.\n* Wherever possible, use a single application-wide mechanism for enforcing access controls.\n* At the code level, make it mandatory for developers to declare the access that is allowed for each resource, and deny access by default.\n* Thoroughly audit and test access controls to ensure they are working as designed.", + finding.mitigation) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) + self.assertEqual("PTART-2024-00002-RT", finding.unique_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.vuln_id_from_tool) + self.assertEqual("PTART-2024-00002", finding.cve) + self.assertEqual("Low", finding.effort_for_fixing) + self.assertEqual("Retest: Test Retest", finding.component_name) + self.assertEqual("2024-09-08", finding.date.strftime("%Y-%m-%d")) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "https://test.example.com") + self.assertEqual(1, len(finding.unsaved_files)) + screenshot = finding.unsaved_files[0] + self.assertEqual("Yet another Screenshot.png", screenshot["title"]) + self.assertTrue(screenshot["data"].startswith("iVBORw0KGgoAAAAN"), "Invalid Screenshot Data") From a75d562aeb26fd719f8a316b5c0505367581ee6d Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:55:34 +0200 Subject: [PATCH 08/38] :bug: fix tenable #11102 (#11103) * :bug: fix tenable #11102 * add unittest --- dojo/tools/tenable/csv_format.py | 2 +- unittests/scans/tenable/issue_11102.csv | 61 +++++++++++++++++++++++++ unittests/tools/test_tenable_parser.py | 10 ++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 unittests/scans/tenable/issue_11102.csv diff --git a/dojo/tools/tenable/csv_format.py b/dojo/tools/tenable/csv_format.py index c1ea9fc2c8..2c2e013446 100644 --- a/dojo/tools/tenable/csv_format.py +++ b/dojo/tools/tenable/csv_format.py @@ -100,7 +100,7 @@ def get_findings(self, filename: str, test: Test): severity = self._convert_severity(raw_severity) # Other text fields description = row.get("Synopsis", row.get("definition.synopsis", "N/A")) - mitigation = str(row.get("Solution", row.get("definition.solution", "N/A"))) + mitigation = str(row.get("Solution", row.get("definition.solution", row.get("Steps to Remediate", "N/A")))) impact = row.get("Description", row.get("definition.description", "N/A")) references = row.get("See Also", row.get("definition.see_also", "N/A")) # Determine if the current row has already been processed diff --git a/unittests/scans/tenable/issue_11102.csv b/unittests/scans/tenable/issue_11102.csv new file mode 100644 index 0000000000..4c901ff864 --- /dev/null +++ b/unittests/scans/tenable/issue_11102.csv @@ -0,0 +1,61 @@ +"Plugin","Plugin Name","Family","Severity","IP Address","Protocol","Port","Exploit?","Repository","MAC Address","DNS Name","NetBIOS Name","Plugin Output","Synopsis","Description","Steps to Remediate","See Also","Risk Factor","STIG Severity","Vulnerability Priority Rating","CVSS V2 Base Score","CVSS V3 Base Score","CVSS V2 Temporal Score","CVSS V3 Temporal Score","CVSS V2 Vector","CVSS V3 Vector","CPE","CVE","BID","Cross References","First Discovered","Last Observed","Vuln Publication Date","Patch Publication Date","Plugin Publication Date","Plugin Modification Date","Exploit Ease","Exploit Frameworks","Check Type","Version","Recast Risk Comment","Accept Risk Comment","Agent ID","Host ID" +"42873","SSL Medium Strength Cipher Suites Supported (SWEET32)","General","High","1.2.3.4","TCP","443","No","Individual Scan","fa:16:3e:e6:0b:98","","","Plugin Output: + Medium Strength Ciphers (> 64-bit and < 112-bit key, or 3DES) + + Name Code KEX Auth Encryption MAC + ---------------------- ---------- --- ---- --------------------- --- + ECDHE-RSA-DES-CBC3-SHA 0xC0, 0x12 ECDH RSA 3DES-CBC(168) SHA1 + DES-CBC3-SHA 0x00, 0x0A RSA RSA 3DES-CBC(168) SHA1 + +The fields above are : + + {Tenable ciphername} + {Cipher ID code} + Kex={key exchange} + Auth={authentication} + Encrypt={symmetric encryption method} + MAC={message authentication code} + {export flag}","The remote service supports the use of medium strength SSL ciphers.","The remote host supports the use of SSL ciphers that offer medium strength encryption. Nessus regards medium strength as any encryption that uses key lengths at least 64 bits and less than 112 bits, or else that uses the 3DES encryption suite. + +Note that it is considerably easier to circumvent medium strength encryption if the attacker is on the same physical network.","Reconfigure the affected application if possible to avoid use of medium strength ciphers.","https://www.openssl.org/blog/blog/2016/08/24/sweet32/ +https://sweet32.info","Medium","","5.1","5.0","7.5","","","AV:N/AC:L/Au:N/C:P/I:N/A:N","AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","","CVE-2016-2183","","","Feb 9, 2024 10:48:42 UTC","Oct 17, 2024 17:24:54 UTC","Aug 24, 2016 12:00:00 UTC","N/A","Nov 23, 2009 12:00:00 UTC","Feb 3, 2021 12:00:00 UTC","","","remote","1.21","","","","" +"42873","SSL Medium Strength Cipher Suites Supported (SWEET32)","General","High","2.3.4.5","TCP","443","No","Individual Scan","fa:16:3e:e6:0b:98","","","Plugin Output: + Medium Strength Ciphers (> 64-bit and < 112-bit key, or 3DES) + + Name Code KEX Auth Encryption MAC + ---------------------- ---------- --- ---- --------------------- --- + ECDHE-RSA-DES-CBC3-SHA 0xC0, 0x12 ECDH RSA 3DES-CBC(168) SHA1 + DES-CBC3-SHA 0x00, 0x0A RSA RSA 3DES-CBC(168) SHA1 + +The fields above are : + + {Tenable ciphername} + {Cipher ID code} + Kex={key exchange} + Auth={authentication} + Encrypt={symmetric encryption method} + MAC={message authentication code} + {export flag}","The remote service supports the use of medium strength SSL ciphers.","The remote host supports the use of SSL ciphers that offer medium strength encryption. Nessus regards medium strength as any encryption that uses key lengths at least 64 bits and less than 112 bits, or else that uses the 3DES encryption suite. + +Note that it is considerably easier to circumvent medium strength encryption if the attacker is on the same physical network.","Reconfigure the affected application if possible to avoid use of medium strength ciphers.","https://www.openssl.org/blog/blog/2016/08/24/sweet32/ +https://sweet32.info","Medium","","5.1","5.0","7.5","","","AV:N/AC:L/Au:N/C:P/I:N/A:N","AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","","CVE-2016-2183","","","Feb 9, 2024 10:48:42 UTC","Oct 17, 2024 17:24:54 UTC","Aug 24, 2016 12:00:00 UTC","N/A","Nov 23, 2009 12:00:00 UTC","Feb 3, 2021 12:00:00 UTC","","","remote","1.21","","","","" +"42873","SSL Medium Strength Cipher Suites Supported (SWEET32)","General","High","1.2.3.4","TCP","8443","No","Individual Scan","fa:16:3e:e6:0b:98","","","Plugin Output: + Medium Strength Ciphers (> 64-bit and < 112-bit key, or 3DES) + + Name Code KEX Auth Encryption MAC + ---------------------- ---------- --- ---- --------------------- --- + ECDHE-RSA-DES-CBC3-SHA 0xC0, 0x12 ECDH RSA 3DES-CBC(168) SHA1 + DES-CBC3-SHA 0x00, 0x0A RSA RSA 3DES-CBC(168) SHA1 + +The fields above are : + + {Tenable ciphername} + {Cipher ID code} + Kex={key exchange} + Auth={authentication} + Encrypt={symmetric encryption method} + MAC={message authentication code} + {export flag}","The remote service supports the use of medium strength SSL ciphers.","The remote host supports the use of SSL ciphers that offer medium strength encryption. Nessus regards medium strength as any encryption that uses key lengths at least 64 bits and less than 112 bits, or else that uses the 3DES encryption suite. + +Note that it is considerably easier to circumvent medium strength encryption if the attacker is on the same physical network.","Reconfigure the affected application if possible to avoid use of medium strength ciphers.","https://www.openssl.org/blog/blog/2016/08/24/sweet32/ +https://sweet32.info","Medium","","5.1","5.0","7.5","","","AV:N/AC:L/Au:N/C:P/I:N/A:N","AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","","CVE-2016-2183","","","Feb 9, 2024 10:48:42 UTC","Oct 17, 2024 17:24:54 UTC","Aug 24, 2016 12:00:00 UTC","N/A","Nov 23, 2009 12:00:00 UTC","Feb 3, 2021 12:00:00 UTC","","","remote","1.21","","","","" \ No newline at end of file diff --git a/unittests/tools/test_tenable_parser.py b/unittests/tools/test_tenable_parser.py index e80c3e4462..7be782c49e 100644 --- a/unittests/tools/test_tenable_parser.py +++ b/unittests/tools/test_tenable_parser.py @@ -299,3 +299,13 @@ def test_parse_issue_9612(self): endpoint.clean() self.assertEqual(2, len(findings)) self.assertEqual("Critical", findings[0].severity) + + def test_parse_issue_11102(self): + with open("unittests/scans/tenable/issue_11102.csv", encoding="utf-8") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(2, len(findings)) + self.assertEqual("Reconfigure the affected application if possible to avoid use of medium strength ciphers.", findings[0].mitigation) From 2c76cda09a7e322035b6567a70ac874ddeeccc01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 26 Oct 2024 20:47:57 -0500 Subject: [PATCH 09/38] Bump boto3 from 1.35.45 to 1.35.48 (#11132) Bumps [boto3](https://github.com/boto/boto3) from 1.35.45 to 1.35.48. - [Release notes](https://github.com/boto/boto3/releases) - [Commits](https://github.com/boto/boto3/compare/1.35.45...1.35.48) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a70ef4f810..e52dd84a9c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -69,7 +69,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.35.45 # Required for Celery Broker AWS (SQS) support +boto3==1.35.48 # Required for Celery Broker AWS (SQS) support netaddr==1.3.0 vulners==2.2.3 fontawesomefree==6.6.0 From b1cc77731097e7ff95c389471689d7eaf3e83783 Mon Sep 17 00:00:00 2001 From: John Doe Date: Sun, 27 Oct 2024 18:32:40 +0100 Subject: [PATCH 10/38] Update link to Slack (#11130) Old link does not work --- .github/ISSUE_TEMPLATE/support_request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/support_request.md b/.github/ISSUE_TEMPLATE/support_request.md index 4dc3873471..f575ea0762 100644 --- a/.github/ISSUE_TEMPLATE/support_request.md +++ b/.github/ISSUE_TEMPLATE/support_request.md @@ -7,7 +7,7 @@ assignees: '' --- **Slack us first!** -The easiest and fastest way to help you is via Slack. There's a free and easy signup to join our #defectdojo channel in the OWASP Slack workspace: [Get Access.](https://owasp-slack.herokuapp.com/) +The easiest and fastest way to help you is via Slack. There's a free and easy signup to join our #defectdojo channel in the OWASP Slack workspace: [Get Access.](https://owasp.org/slack/invite) If you're confident you've found a bug, or are allergic to Slack, you can submit an issue anyway. **Be informative** From 4fdd555956e3c952a6e27efbaedacbee2d37f858 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Sun, 27 Oct 2024 12:43:58 -0500 Subject: [PATCH 11/38] JIRA Finding Groups: Accommodate status function inconsistency (#11125) * JIRA Finding Groups: Accommodate status function inconsistency * Fix ruff --- dojo/jira_link/helper.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dojo/jira_link/helper.py b/dojo/jira_link/helper.py index fb0eab686e..860f4f01d1 100644 --- a/dojo/jira_link/helper.py +++ b/dojo/jira_link/helper.py @@ -159,7 +159,13 @@ def can_be_pushed_to_jira(obj, form=None): elif isinstance(obj, Finding_Group): if not obj.findings.all(): return False, f"{to_str_typed(obj)} cannot be pushed to jira as it is empty.", "error_empty" - if "Active" not in obj.status(): + # Accommodating a strange behavior where a finding group sometimes prefers `obj.status` rather than `obj.status()` + try: + not_active = "Active" not in obj.status() + except TypeError: # TypeError: 'str' object is not callable + not_active = "Active" not in obj.status + # Determine if the finding group is not active + if not_active: return False, f"{to_str_typed(obj)} cannot be pushed to jira as it is not active.", "error_inactive" else: From a239d8b0a36fd7cbe512190688799f1ee90152a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Oct 2024 12:46:16 -0500 Subject: [PATCH 12/38] Bump ruff from 0.7.0 to 0.7.1 (#11133) Bumps [ruff](https://github.com/astral-sh/ruff) from 0.7.0 to 0.7.1. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.7.0...0.7.1) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-lint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-lint.txt b/requirements-lint.txt index 4228b8f407..8bf2f34823 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1 +1 @@ -ruff==0.7.0 \ No newline at end of file +ruff==0.7.1 \ No newline at end of file From c63b41ea9e69cffe3ffed4eb520827ed964dd568 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Oct 2024 12:46:36 -0500 Subject: [PATCH 13/38] Bump redis from 5.1.1 to 5.2.0 (#11134) Bumps [redis](https://github.com/redis/redis-py) from 5.1.1 to 5.2.0. - [Release notes](https://github.com/redis/redis-py/releases) - [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES) - [Commits](https://github.com/redis/redis-py/compare/v5.1.1...v5.2.0) --- updated-dependencies: - dependency-name: redis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e52dd84a9c..812c454706 100644 --- a/requirements.txt +++ b/requirements.txt @@ -35,7 +35,7 @@ psycopg[c]==3.2.3 cryptography==43.0.3 python-dateutil==2.9.0.post0 pytz==2024.2 -redis==5.1.1 +redis==5.2.0 requests==2.32.3 sqlalchemy==2.0.36 # Required by Celery broker transport urllib3==1.26.18 From e09130f0e3581f8af2906f269f9ce9c785396df4 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Sun, 27 Oct 2024 18:51:45 +0100 Subject: [PATCH 14/38] update RedHatSatellite bug description (#11101) --- dojo/tools/redhatsatellite/parser.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dojo/tools/redhatsatellite/parser.py b/dojo/tools/redhatsatellite/parser.py index 102f47876f..897273d8a1 100644 --- a/dojo/tools/redhatsatellite/parser.py +++ b/dojo/tools/redhatsatellite/parser.py @@ -62,7 +62,10 @@ def get_findings(self, filename, test): description += "**hosts_applicable_count:** " + str(hosts_applicable_count) + "\n" description += "**installable:** " + str(installable) + "\n" if bugs != []: - description += "**bugs:** " + str(bugs) + "\n" + description += "**bugs:** " + for bug in bugs[:-1]: + description += "[" + bug.get("bug_id") + "](" + bug.get("href") + ")" + ", " + description += "[" + bugs[-1].get("bug_id") + "](" + bugs[-1].get("href") + ")" + "\n" if module_streams != []: description += "**module_streams:** " + str(module_streams) + "\n" description += "**packages:** " + ", ".join(packages) From 0563e0991659a77eab76b96b139b5ad557fe2f55 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Sun, 27 Oct 2024 18:52:58 +0100 Subject: [PATCH 15/38] add RXSA VULNERABILITY_URL (#11097) --- dojo/settings/.settings.dist.py.sha256sum | 2 +- dojo/settings/settings.dist.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index 476d3116d4..def3909d2c 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -42026ac47884ee26fe742e59fb7dc621b5f927ee6ee3c92daf09b97f2a740163 +002b28325f11793c5aa9f09326c2d5cc66de518cce51b2cb4cb681a920b89909 diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 1493afadd9..846639f07a 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1736,6 +1736,7 @@ def saml2_attrib_map_format(dict): "USN": "https://ubuntu.com/security/notices/", # e.g. https://ubuntu.com/security/notices/USN-6642-1 "DLA": "https://security-tracker.debian.org/tracker/", # e.g. https://security-tracker.debian.org/tracker/DLA-3917-1 "ELSA": "https://linux.oracle.com/errata/&&.html", # e.g. https://linux.oracle.com/errata/ELSA-2024-12714.html + "RXSA": "https://errata.rockylinux.org/", # e.g. https://errata.rockylinux.org/RXSA-2024:4928 } # List of acceptable file types that can be uploaded to a given object via arbitrary file upload FILE_UPLOAD_TYPES = env("DD_FILE_UPLOAD_TYPES") From a3e3e1786f4c46907dddde4630678939cfb06a93 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Mon, 28 Oct 2024 09:18:03 -0500 Subject: [PATCH 16/38] OSV Parser: Robustify (#11115) --- dojo/tools/osv_scanner/parser.py | 38 +++++++++++++++++++------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/dojo/tools/osv_scanner/parser.py b/dojo/tools/osv_scanner/parser.py index 42e9408825..f91ec10f7d 100644 --- a/dojo/tools/osv_scanner/parser.py +++ b/dojo/tools/osv_scanner/parser.py @@ -30,26 +30,34 @@ def get_findings(self, file, test): except json.decoder.JSONDecodeError: return [] findings = [] - for result in data["results"]: - source_path = result["source"]["path"] - source_type = result["source"]["type"] - for package in result["packages"]: - package_name = package["package"]["name"] - package_version = package["package"]["version"] - package_ecosystem = package["package"]["ecosystem"] - for vulnerability in package["vulnerabilities"]: + for result in data.get("results", []): + # Extract source locations if present + source_path = result.get("source", {}).get("path", "") + source_type = result.get("source", {}).get("type", "") + for package in result.get("packages", []): + package_name = package.get("package", {}).get("name") + package_version = package.get("package", {}).get("version") + package_ecosystem = package.get("package", {}).get("ecosystem", "") + for vulnerability in package.get("vulnerabilities", []): vulnerabilityid = vulnerability.get("id", "") vulnerabilitysummary = vulnerability.get("summary", "") - vulnerabilitydetails = vulnerability["details"] - vulnerabilitypackagepurl = vulnerability["affected"][0].get("package", "") - if vulnerabilitypackagepurl != "": - vulnerabilitypackagepurl = vulnerabilitypackagepurl["purl"] - cwe = vulnerability["affected"][0]["database_specific"].get("cwes", None) - if cwe is not None: - cwe = cwe[0]["cweId"] + vulnerabilitydetails = vulnerability.get("details", "") + vulnerabilitypackagepurl = "" + cwe = None + # Make sure we have an affected section to work with + if (affected := vulnerability.get("affected")) is not None: + if len(affected) > 0: + # Pull the package purl if present + if (vulnerabilitypackage := affected[0].get("package", "")) != "": + vulnerabilitypackagepurl = vulnerabilitypackage.get("purl", "") + # Extract the CWE + if (cwe := affected[0].get("database_specific", {}).get("cwes", None)) is not None: + cwe = cwe[0]["cweId"] + # Create some references reference = "" for ref in vulnerability.get("references"): reference += ref.get("url") + "\n" + # Define the description description = vulnerabilitysummary + "\n" description += "**source_type**: " + source_type + "\n" description += "**package_ecosystem**: " + package_ecosystem + "\n" From b60eefd9edafd2ae7ad74ac59acea7cb54b8ae60 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Mon, 28 Oct 2024 09:38:38 -0500 Subject: [PATCH 17/38] Threat Uploads: Server side file extension validation + force downloads (#11135) * Threat Uploads: Server side file extension validation + force downloads * Fix ruff --- dojo/engagement/views.py | 5 +++-- dojo/forms.py | 17 +++++++++++++++++ dojo/utils.py | 27 +++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/dojo/engagement/views.py b/dojo/engagement/views.py index ea73bd80c6..b813a9c275 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -17,7 +17,7 @@ from django.db import DEFAULT_DB_ALIAS from django.db.models import Count, Q from django.db.models.query import Prefetch, QuerySet -from django.http import FileResponse, HttpRequest, HttpResponse, HttpResponseRedirect, QueryDict, StreamingHttpResponse +from django.http import HttpRequest, HttpResponse, HttpResponseRedirect, QueryDict, StreamingHttpResponse from django.shortcuts import get_object_or_404, render from django.urls import Resolver404, reverse from django.utils import timezone @@ -100,6 +100,7 @@ add_success_message_to_response, async_delete, calculate_grade, + generate_file_response_from_file_path, get_cal_event, get_page_items, get_return_url, @@ -1516,7 +1517,7 @@ def upload_threatmodel(request, eid): @user_is_authorized(Engagement, Permissions.Engagement_View, "eid") def view_threatmodel(request, eid): eng = get_object_or_404(Engagement, pk=eid) - return FileResponse(open(eng.tmodel_path, "rb")) + return generate_file_response_from_file_path(eng.tmodel_path) @user_is_authorized(Engagement, Permissions.Engagement_View, "eid") diff --git a/dojo/forms.py b/dojo/forms.py index 6fe83668d1..cb1e670054 100644 --- a/dojo/forms.py +++ b/dojo/forms.py @@ -752,6 +752,23 @@ class UploadThreatForm(forms.Form): attrs={"accept": ".jpg,.png,.pdf"}), label="Select Threat Model") + def clean(self): + if (file := self.cleaned_data.get("file", None)) is not None: + ext = os.path.splitext(file.name)[1] # [0] returns path+filename + valid_extensions = [".jpg", ".png", ".pdf"] + if ext.lower() not in valid_extensions: + if accepted_extensions := f"{', '.join(valid_extensions)}": + msg = ( + "Unsupported extension. Supported extensions are as " + f"follows: {accepted_extensions}" + ) + else: + msg = ( + "File uploads are prohibited due to the list of acceptable " + "file extensions being empty" + ) + raise ValidationError(msg) + class MergeFindings(forms.ModelForm): FINDING_ACTION = (("", "Select an Action"), ("inactive", "Inactive"), ("delete", "Delete")) diff --git a/dojo/utils.py b/dojo/utils.py index 470d860772..8bbd531210 100644 --- a/dojo/utils.py +++ b/dojo/utils.py @@ -5,6 +5,7 @@ import logging import mimetypes import os +import pathlib import re from calendar import monthrange from datetime import date, datetime, timedelta @@ -2616,14 +2617,32 @@ def generate_file_response(file_object: FileUpload) -> FileResponse: raise TypeError(msg) # Determine the path of the file on disk within the MEDIA_ROOT file_path = f"{settings.MEDIA_ROOT}/{file_object.file.url.lstrip(settings.MEDIA_URL)}" - _, file_extension = os.path.splitext(file_path) + + return generate_file_response_from_file_path( + file_path, file_name=file_object.title, file_size=file_object.file.size, + ) + + +def generate_file_response_from_file_path( + file_path: str, file_name: str | None = None, file_size: int | None = None, +) -> FileResponse: + """Serve an local file in a uniformed way.""" + # Determine the file path + file_path_without_extension, file_extension = os.path.splitext(file_path) + # Determine the file name if not supplied + if file_name is None: + file_name = file_path_without_extension.rsplit("/")[-1] + # Determine the file size if not supplied + if file_size is None: + file_size = pathlib.Path(file_path).stat().st_size # Generate the FileResponse + full_file_name = f"{file_name}{file_extension}" response = FileResponse( open(file_path, "rb"), - filename=f"{file_object.title}{file_extension}", + filename=full_file_name, content_type=f"{mimetypes.guess_type(file_path)}", ) # Add some important headers - response["Content-Disposition"] = f'attachment; filename="{file_object.title}{file_extension}"' - response["Content-Length"] = file_object.file.size + response["Content-Disposition"] = f'attachment; filename="{full_file_name}"' + response["Content-Length"] = file_size return response From cb7a7d09629a12f33bd02541ae3d9152193ff7a2 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 28 Oct 2024 14:59:19 +0000 Subject: [PATCH 18/38] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 06cdce1889..4b74883bf0 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.40.0-dev", + "version": "2.39.3", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index f21e8362fa..ee1a414db8 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = "2.39.2" +__version__ = "2.39.3" __url__ = "https://github.com/DefectDojo/django-DefectDojo" __docs__ = "https://documentation.defectdojo.com" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index ae1c256e0e..cf5789792f 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.40.0-dev" +appVersion: "2.39.3" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.156-dev +version: 1.6.156 icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From f539b1b686c42ebcf57f2cb2f4a19dfe8de15792 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 28 Oct 2024 15:27:32 +0000 Subject: [PATCH 19/38] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 4b74883bf0..06cdce1889 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.39.3", + "version": "2.40.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index ee1a414db8..0dc36e95a1 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = "2.39.3" +__version__ = "2.40.0-dev" __url__ = "https://github.com/DefectDojo/django-DefectDojo" __docs__ = "https://documentation.defectdojo.com" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index cf5789792f..3f1a22acc9 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.39.3" +appVersion: "2.40.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.156 +version: 1.6.157-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 39a3e0c9beb3540b7f31f55eb36f4dbb806167b0 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 28 Oct 2024 15:27:32 +0000 Subject: [PATCH 20/38] Update versions in application files --- components/package.json | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/package.json b/components/package.json index 4b74883bf0..06cdce1889 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.39.3", + "version": "2.40.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index cf5789792f..3f1a22acc9 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.39.3" +appVersion: "2.40.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.156 +version: 1.6.157-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From bc19fc321a4be13f6b100f6eac64ef4a0faad624 Mon Sep 17 00:00:00 2001 From: Ross Esposito Date: Mon, 28 Oct 2024 11:34:13 -0500 Subject: [PATCH 21/38] Fixing checksum --- dojo/settings/.settings.dist.py.sha256sum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index def3909d2c..2a9d5c52e5 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -002b28325f11793c5aa9f09326c2d5cc66de518cce51b2cb4cb681a920b89909 +6a90a111e2b89eb2c400945c80ff76c64b135d78b84fdf6b09a6b83569946904 From 9a8fbc4fab64397be0c296e81a42755c3069db7f Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Mon, 28 Oct 2024 12:16:03 -0500 Subject: [PATCH 22/38] Import/Reimport: Restore Defaults (#11147) --- dojo/api_v2/serializers.py | 67 ++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index e769b15b98..56a1826506 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -2065,7 +2065,6 @@ class CommonImportScanSerializer(serializers.Serializer): help_text="Override the verified setting from the tool.", ) - scan_type = serializers.ChoiceField(choices=get_choices_sorted()) # TODO: why do we allow only existing endpoints? endpoint_to_add = serializers.PrimaryKeyRelatedField( queryset=Endpoint.objects.all(), @@ -2093,26 +2092,8 @@ class CommonImportScanSerializer(serializers.Serializer): lead = serializers.PrimaryKeyRelatedField( allow_null=True, default=None, queryset=User.objects.all(), ) - tags = TagListSerializerField( - required=False, allow_empty=True, help_text="Add tags that help describe this scan.", - ) - close_old_findings = serializers.BooleanField( - required=False, - default=False, - help_text="Select if old findings no longer present in the report get closed as mitigated when importing. " - "If service has been set, only the findings for this service will be closed.", - ) - close_old_findings_product_scope = serializers.BooleanField( - required=False, - default=False, - help_text="Select if close_old_findings applies to all findings of the same type in the product. " - "By default, it is false meaning that only old findings of the same type in the engagement are in scope.", - ) push_to_jira = serializers.BooleanField(default=False) environment = serializers.CharField(required=False) - version = serializers.CharField( - required=False, help_text="Version that was scanned.", - ) build_id = serializers.CharField( required=False, help_text="ID of the build that was scanned.", ) @@ -2281,11 +2262,28 @@ def setup_common_context(self, data: dict) -> dict: class ImportScanSerializer(CommonImportScanSerializer): - + scan_type = serializers.ChoiceField(choices=get_choices_sorted()) engagement = serializers.PrimaryKeyRelatedField( queryset=Engagement.objects.all(), required=False, ) - + tags = TagListSerializerField( + required=False, allow_empty=True, help_text="Add tags that help describe this scan.", + ) + close_old_findings = serializers.BooleanField( + required=False, + default=False, + help_text="Select if old findings no longer present in the report get closed as mitigated when importing. " + "If service has been set, only the findings for this service will be closed.", + ) + close_old_findings_product_scope = serializers.BooleanField( + required=False, + default=False, + help_text="Select if close_old_findings applies to all findings of the same type in the product. " + "By default, it is false meaning that only old findings of the same type in the engagement are in scope.", + ) + version = serializers.CharField( + required=False, help_text="Version that was scanned.", + ) # extra fields populated in response # need to use the _id suffix as without the serializer framework gets # confused @@ -2341,9 +2339,36 @@ class ReImportScanSerializer(TaggitSerializer, CommonImportScanSerializer): do_not_reactivate = serializers.BooleanField( default=False, required=False, help_text=help_do_not_reactivate, ) + scan_type = serializers.ChoiceField( + choices=get_choices_sorted(), required=True, + ) test = serializers.PrimaryKeyRelatedField( required=False, queryset=Test.objects.all(), ) + # Close the old findings if the parameter is not provided. This is to + # maintain the old API behavior after reintroducing the close_old_findings parameter + # also for ReImport. + close_old_findings = serializers.BooleanField( + required=False, + default=True, + help_text="Select if old findings no longer present in the report get closed as mitigated when importing.", + ) + close_old_findings_product_scope = serializers.BooleanField( + required=False, + default=False, + help_text="Select if close_old_findings applies to all findings of the same type in the product. " + "By default, it is false meaning that only old findings of the same type in the engagement are in scope. " + "Note that this only applies on the first call to reimport-scan.", + ) + version = serializers.CharField( + required=False, + help_text="Version that will be set on existing Test object. Leave empty to leave existing value in place.", + ) + tags = TagListSerializerField( + required=False, + allow_empty=True, + help_text="Modify existing tags that help describe this scan. (Existing test tags will be overwritten)", + ) def set_context( self, From a5567597e5e84b3cd0c27f50af51641b7d737566 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 28 Oct 2024 18:24:31 +0000 Subject: [PATCH 23/38] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 06cdce1889..805b16ff7c 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.40.0-dev", + "version": "2.39.4", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index ee1a414db8..9572cd8932 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = "2.39.3" +__version__ = "2.39.4" __url__ = "https://github.com/DefectDojo/django-DefectDojo" __docs__ = "https://documentation.defectdojo.com" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 3f1a22acc9..5337b2b705 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.40.0-dev" +appVersion: "2.39.4" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.157-dev +version: 1.6.157 icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 868d4e4e7f22b0f2a5d28b5792c57679d60f118c Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 28 Oct 2024 18:53:19 +0000 Subject: [PATCH 24/38] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 805b16ff7c..06cdce1889 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.39.4", + "version": "2.40.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index 9572cd8932..0dc36e95a1 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = "2.39.4" +__version__ = "2.40.0-dev" __url__ = "https://github.com/DefectDojo/django-DefectDojo" __docs__ = "https://documentation.defectdojo.com" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 5337b2b705..ffac3d938b 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.39.4" +appVersion: "2.40.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.157 +version: 1.6.158-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 83449c76dced2501f801da38ea2868d91afda78c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:23:21 -0500 Subject: [PATCH 25/38] Bump boto3 from 1.35.48 to 1.35.49 (#11141) Bumps [boto3](https://github.com/boto/boto3) from 1.35.48 to 1.35.49. - [Release notes](https://github.com/boto/boto3/releases) - [Commits](https://github.com/boto/boto3/compare/1.35.48...1.35.49) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 812c454706..8e6fd1a178 100644 --- a/requirements.txt +++ b/requirements.txt @@ -69,7 +69,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.35.48 # Required for Celery Broker AWS (SQS) support +boto3==1.35.49 # Required for Celery Broker AWS (SQS) support netaddr==1.3.0 vulners==2.2.3 fontawesomefree==6.6.0 From 314a9da08f31a9795716c248281740fb3406c7bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:34:58 -0500 Subject: [PATCH 26/38] Bump uwsgi from 2.0.26 to 2.0.28 (#11142) Bumps [uwsgi](https://uwsgi-docs.readthedocs.io/en/latest/) from 2.0.26 to 2.0.28. --- updated-dependencies: - dependency-name: uwsgi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8e6fd1a178..1176e6ac57 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,7 +39,7 @@ redis==5.2.0 requests==2.32.3 sqlalchemy==2.0.36 # Required by Celery broker transport urllib3==1.26.18 -uWSGI==2.0.26 +uWSGI==2.0.28 vobject==0.9.8 whitenoise==5.2.0 titlecase==2.4.1 From 517f7f49ba2fe7ec4629e9bc053d21f9d5b95fe9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:02:02 -0500 Subject: [PATCH 27/38] Bump python-gitlab from 4.13.0 to 5.0.0 (#11140) Bumps [python-gitlab](https://github.com/python-gitlab/python-gitlab) from 4.13.0 to 5.0.0. - [Release notes](https://github.com/python-gitlab/python-gitlab/releases) - [Changelog](https://github.com/python-gitlab/python-gitlab/blob/main/CHANGELOG.md) - [Commits](https://github.com/python-gitlab/python-gitlab/compare/v4.13.0...v5.0.0) --- updated-dependencies: - dependency-name: python-gitlab dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1176e6ac57..3e560a89d6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -46,7 +46,7 @@ titlecase==2.4.1 social-auth-app-django==5.4.2 social-auth-core==4.5.4 gitpython==3.1.43 -python-gitlab==4.13.0 +python-gitlab==5.0.0 cpe==1.3.1 packageurl-python==0.16.0 django-crum==0.7.9 From da2df33d47eb5a30bb26d0575e9b3d44a6b4a9df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 20:29:11 -0500 Subject: [PATCH 28/38] Bump boto3 from 1.35.49 to 1.35.50 (#11155) Bumps [boto3](https://github.com/boto/boto3) from 1.35.49 to 1.35.50. - [Release notes](https://github.com/boto/boto3/releases) - [Commits](https://github.com/boto/boto3/compare/1.35.49...1.35.50) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3e560a89d6..8c2b093b74 100644 --- a/requirements.txt +++ b/requirements.txt @@ -69,7 +69,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.35.49 # Required for Celery Broker AWS (SQS) support +boto3==1.35.50 # Required for Celery Broker AWS (SQS) support netaddr==1.3.0 vulners==2.2.3 fontawesomefree==6.6.0 From 518846c7597af774337e71d90a44fc78bae947a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:58:00 -0500 Subject: [PATCH 29/38] Bump bleach from 6.1.0 to 6.2.0 (#11161) Bumps [bleach](https://github.com/mozilla/bleach) from 6.1.0 to 6.2.0. - [Changelog](https://github.com/mozilla/bleach/blob/main/CHANGES) - [Commits](https://github.com/mozilla/bleach/compare/v6.1.0...v6.2.0) --- updated-dependencies: - dependency-name: bleach dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8c2b093b74..3626732dc7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # requirements.txt for DefectDojo using Python 3.x asteval==1.0.5 -bleach==6.1.0 +bleach==6.2.0 bleach[css] celery==5.4.0 defusedxml==0.7.1 From fc936234b17fcfbebce99b543d6170fefc4719f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:58:44 -0500 Subject: [PATCH 30/38] Bump boto3 from 1.35.50 to 1.35.51 (#11160) Bumps [boto3](https://github.com/boto/boto3) from 1.35.50 to 1.35.51. - [Release notes](https://github.com/boto/boto3/releases) - [Commits](https://github.com/boto/boto3/compare/1.35.50...1.35.51) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3626732dc7..df6b56730d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -69,7 +69,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.35.50 # Required for Celery Broker AWS (SQS) support +boto3==1.35.51 # Required for Celery Broker AWS (SQS) support netaddr==1.3.0 vulners==2.2.3 fontawesomefree==6.6.0 From 3368c82c4ef77fb11cdd2dd805a9deec556b1ba1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:25:47 -0500 Subject: [PATCH 31/38] Update Helm release postgresql from 16.0.6 to ~16.1.0 (helm/defectdojo/Chart.yaml) (#11164) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- helm/defectdojo/Chart.lock | 6 +++--- helm/defectdojo/Chart.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index 49d15928ea..611d1100a4 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -1,12 +1,12 @@ dependencies: - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 16.0.0 + version: 16.1.0 - name: postgresql-ha repository: https://charts.bitnami.com/bitnami version: 9.4.11 - name: redis repository: https://charts.bitnami.com/bitnami version: 19.6.4 -digest: sha256:43166002555f6bdaac719d3d54e56a3e069b17ed29acd1c70951b7b99b102ae7 -generated: "2024-10-02T16:37:38.736091938Z" +digest: sha256:499d18e7070e7752e0dccfa2187d755570e105eb21cae37d6f0623a333997db8 +generated: "2024-10-30T17:58:45.866148081Z" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index ffac3d938b..af7a77d7b5 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -10,7 +10,7 @@ maintainers: url: https://github.com/DefectDojo/django-DefectDojo dependencies: - name: postgresql - version: ~16.0.0 + version: ~16.1.0 repository: "https://charts.bitnami.com/bitnami" condition: postgresql.enabled - name: postgresql-ha From ae9718ff90f993fb1cac1f9de9f4f75c06a764b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:25:29 -0500 Subject: [PATCH 32/38] Bump jquery-ui from 1.14.0 to 1.14.1 in /components (#11170) Bumps [jquery-ui](https://github.com/jquery/jquery-ui) from 1.14.0 to 1.14.1. - [Release notes](https://github.com/jquery/jquery-ui/releases) - [Commits](https://github.com/jquery/jquery-ui/compare/1.14.0...1.14.1) --- updated-dependencies: - dependency-name: jquery-ui dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- components/package.json | 2 +- components/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/package.json b/components/package.json index 7d7c9d1b85..74a5293b38 100644 --- a/components/package.json +++ b/components/package.json @@ -26,7 +26,7 @@ "google-code-prettify": "^1.0.0", "jquery": "^3.7.1", "jquery-highlight": "3.5.0", - "jquery-ui": "1.14.0", + "jquery-ui": "1.14.1", "jquery.cookie": "1.4.1", "jquery.flot.tooltip": "^0.9.0", "jquery.hotkeys": "jeresig/jquery.hotkeys#master", diff --git a/components/yarn.lock b/components/yarn.lock index 952d09ff22..7f7ddd04d7 100644 --- a/components/yarn.lock +++ b/components/yarn.lock @@ -678,10 +678,10 @@ jquery-highlight@3.5.0: dependencies: jquery ">= 1.0.0" -jquery-ui@1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.14.0.tgz#b75d417826f0bab38125f907356d2e3313a9c6d5" - integrity sha512-mPfYKBoRCf0MzaT2cyW5i3IuZ7PfTITaasO5OFLAQxrHuI+ZxruPa+4/K1OMNT8oElLWGtIxc9aRbyw20BKr8g== +jquery-ui@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.14.1.tgz#ba342ea3ffff662b787595391f607d923313e040" + integrity sha512-DhzsYH8VeIvOaxwi+B/2BCsFFT5EGjShdzOcm5DssWjtcpGWIMsn66rJciDA6jBruzNiLf1q0KvwMoX1uGNvnQ== dependencies: jquery ">=1.12.0 <5.0.0" From f401370cf0fae5a1d3b16eb4a0054d8b8d04f742 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:25:59 -0500 Subject: [PATCH 33/38] Bump boto3 from 1.35.51 to 1.35.52 (#11171) Bumps [boto3](https://github.com/boto/boto3) from 1.35.51 to 1.35.52. - [Release notes](https://github.com/boto/boto3/releases) - [Commits](https://github.com/boto/boto3/compare/1.35.51...1.35.52) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index df6b56730d..4bee079576 100644 --- a/requirements.txt +++ b/requirements.txt @@ -69,7 +69,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.35.51 # Required for Celery Broker AWS (SQS) support +boto3==1.35.52 # Required for Celery Broker AWS (SQS) support netaddr==1.3.0 vulners==2.2.3 fontawesomefree==6.6.0 From bf7ca81d107302c3c6e2d6d128197ec3cf5f4be2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 11:52:58 -0500 Subject: [PATCH 34/38] Bump cvss from 3.2 to 3.3 (#11177) Bumps [cvss](https://github.com/RedHatProductSecurity/cvss) from 3.2 to 3.3. - [Release notes](https://github.com/RedHatProductSecurity/cvss/releases) - [Commits](https://github.com/RedHatProductSecurity/cvss/compare/v3.2...v3.3) --- updated-dependencies: - dependency-name: cvss dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4bee079576..d5134c5cd0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -58,7 +58,7 @@ vcrpy==6.0.2 vcrpy-unittest==0.1.7 django-tagulous==2.1.0 PyJWT==2.9.0 -cvss==3.2 +cvss==3.3 django-fieldsignals==0.7.0 hyperlink==21.0.0 django-test-migrations==1.4.0 From abf8f698aab832c5c7612f1b0519a59b229ef772 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 11:53:17 -0500 Subject: [PATCH 35/38] Bump drf-spectacular-sidecar from 2024.7.1 to 2024.11.1 (#11176) Bumps [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar) from 2024.7.1 to 2024.11.1. - [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2024.7.1...2024.11.1) --- updated-dependencies: - dependency-name: drf-spectacular-sidecar dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d5134c5cd0..bd195e7bef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -64,7 +64,7 @@ hyperlink==21.0.0 django-test-migrations==1.4.0 djangosaml2==1.9.3 drf-spectacular==0.27.2 -drf-spectacular-sidecar==2024.7.1 +drf-spectacular-sidecar==2024.11.1 django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 From eb66211f6bb899f0efe8fb0adf795b95b5cd0c14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 11:53:33 -0500 Subject: [PATCH 36/38] Bump boto3 from 1.35.52 to 1.35.53 (#11175) Bumps [boto3](https://github.com/boto/boto3) from 1.35.52 to 1.35.53. - [Release notes](https://github.com/boto/boto3/releases) - [Commits](https://github.com/boto/boto3/compare/1.35.52...1.35.53) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index bd195e7bef..949f2e5793 100644 --- a/requirements.txt +++ b/requirements.txt @@ -69,7 +69,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.35.52 # Required for Celery Broker AWS (SQS) support +boto3==1.35.53 # Required for Celery Broker AWS (SQS) support netaddr==1.3.0 vulners==2.2.3 fontawesomefree==6.6.0 From 7c75f6165dd6225ef8cc841efed83eb3ad33c263 Mon Sep 17 00:00:00 2001 From: kiblik <5609770+kiblik@users.noreply.github.com> Date: Fri, 1 Nov 2024 18:04:12 +0100 Subject: [PATCH 37/38] Ruff: Add and fix D403 (#11063) --- dojo/utils.py | 2 +- ruff.toml | 2 +- unittests/test_apiv2_notifications.py | 2 +- unittests/tools/test_github_vulnerability_parser.py | 8 ++++---- unittests/tools/test_sarif_parser.py | 2 +- unittests/tools/test_sonarqube_parser.py | 2 +- unittests/tools/test_tenable_parser.py | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dojo/utils.py b/dojo/utils.py index 65d6bdf728..0e340f2ce0 100644 --- a/dojo/utils.py +++ b/dojo/utils.py @@ -2222,7 +2222,7 @@ def mass_model_updater(model_type, models, function, fields, page_size=1000, ord def to_str_typed(obj): - """for code that handles multiple types of objects, print not only __str__ but prefix the type of the object""" + """For code that handles multiple types of objects, print not only __str__ but prefix the type of the object""" return f"{type(obj)}: {obj}" diff --git a/ruff.toml b/ruff.toml index 25e456a548..ac0f0ece1e 100644 --- a/ruff.toml +++ b/ruff.toml @@ -37,7 +37,7 @@ select = [ "W", "C90", "I", - "D2", "D3", + "D2", "D3", "D403", "UP", "YTT", "ASYNC", diff --git a/unittests/test_apiv2_notifications.py b/unittests/test_apiv2_notifications.py index d24a05f596..09d57dfd9f 100644 --- a/unittests/test_apiv2_notifications.py +++ b/unittests/test_apiv2_notifications.py @@ -57,7 +57,7 @@ def test_notification_template_multiple(self): self.assertEqual("Notification template already exists", r.json()["non_field_errors"][0]) def test_user_notifications(self): - """creates user and checks if template is assigned""" + """Creates user and checks if template is assigned""" user = {"user": self.create_test_user()} r = self.client.get(reverse("notifications-list"), user, format="json") self.assertEqual(r.status_code, 200) diff --git a/unittests/tools/test_github_vulnerability_parser.py b/unittests/tools/test_github_vulnerability_parser.py index c0c9a0350e..00321647bf 100644 --- a/unittests/tools/test_github_vulnerability_parser.py +++ b/unittests/tools/test_github_vulnerability_parser.py @@ -9,14 +9,14 @@ class TestGithubVulnerabilityParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - """sample with zero vulnerability""" + """Sample with zero vulnerability""" with open("unittests/scans/github_vulnerability/github-0-vuln.json", encoding="utf-8") as testfile: parser = GithubVulnerabilityParser() findings = parser.get_findings(testfile, Test()) self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): - """sample with one vulnerability""" + """Sample with one vulnerability""" with open("unittests/scans/github_vulnerability/github-1-vuln.json", encoding="utf-8") as testfile: parser = GithubVulnerabilityParser() findings = parser.get_findings(testfile, Test()) @@ -36,7 +36,7 @@ def test_parse_file_with_one_vuln_has_one_findings(self): self.assertEqual(finding.unique_id_from_tool, "aabbccddeeff1122334401") def test_parse_file_with_one_vuln_has_one_finding_and_dependabot_direct_link(self): - """sample with one vulnerability""" + """Sample with one vulnerability""" with open("unittests/scans/github_vulnerability/github-1-vuln-repo-dependabot-link.json", encoding="utf-8") as testfile: parser = GithubVulnerabilityParser() findings = parser.get_findings(testfile, Test()) @@ -56,7 +56,7 @@ def test_parse_file_with_one_vuln_has_one_finding_and_dependabot_direct_link(sel self.assertEqual(finding.unique_id_from_tool, "aabbccddeeff1122334401") def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - """sample with five vulnerability""" + """Sample with five vulnerability""" with open("unittests/scans/github_vulnerability/github-5-vuln.json", encoding="utf-8") as testfile: parser = GithubVulnerabilityParser() findings = parser.get_findings(testfile, Test()) diff --git a/unittests/tools/test_sarif_parser.py b/unittests/tools/test_sarif_parser.py index 0ae50e659f..aafa91d09e 100644 --- a/unittests/tools/test_sarif_parser.py +++ b/unittests/tools/test_sarif_parser.py @@ -28,7 +28,7 @@ def test_example_report(self): self.common_checks(finding) def test_suppression_report(self): - """test report file having different suppression definitions""" + """Test report file having different suppression definitions""" with open(path.join(path.dirname(__file__), "../scans/sarif/suppression_test.sarif"), encoding="utf-8") as testfile: parser = SarifParser() findings = parser.get_findings(testfile, Test()) diff --git a/unittests/tools/test_sonarqube_parser.py b/unittests/tools/test_sonarqube_parser.py index 16b80aa9eb..ef4912510b 100644 --- a/unittests/tools/test_sonarqube_parser.py +++ b/unittests/tools/test_sonarqube_parser.py @@ -245,7 +245,7 @@ def test_detailed_parse_file_with_table_in_table(self): my_file_handle.close() def test_detailed_parse_file_with_rule_undefined(self): - """the vulnerability's rule is not in the list of rules""" + """The vulnerability's rule is not in the list of rules""" my_file_handle, _product, _engagement, test = self.init( get_unit_tests_path() + "/scans/sonarqube/sonar-rule-undefined.html", ) diff --git a/unittests/tools/test_tenable_parser.py b/unittests/tools/test_tenable_parser.py index 7be782c49e..cde5119fe9 100644 --- a/unittests/tools/test_tenable_parser.py +++ b/unittests/tools/test_tenable_parser.py @@ -155,7 +155,7 @@ def test_parse_some_findings_samples_nessus_legacy(self): self.assertEqual("CVE-2005-1794", vulnerability_id) def test_parse_some_findings_with_cvssv3_nessus_legacy(self): - """test with cvssv3""" + """Test with cvssv3""" with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_with_cvssv3.nessus"), encoding="utf-8") as testfile: parser = TenableParser() findings = parser.get_findings(testfile, self.create_test()) From ab2b88ef5b20b87ac99c19257f72a2561c5bc7a8 Mon Sep 17 00:00:00 2001 From: kiblik <5609770+kiblik@users.noreply.github.com> Date: Fri, 1 Nov 2024 19:11:29 +0100 Subject: [PATCH 38/38] Ruff: Add and fix S101 (#11066) --- dojo/middleware.py | 16 ++++++---- ruff.toml | 2 +- tests/Import_scanner_test.py | 8 ++--- tests/notifications_test.py | 41 +++++++++++++------------- unittests/test_rest_framework.py | 50 ++++++++++++++++++-------------- 5 files changed, 63 insertions(+), 54 deletions(-) diff --git a/dojo/middleware.py b/dojo/middleware.py index 29eff445b3..9fcb8a51db 100644 --- a/dojo/middleware.py +++ b/dojo/middleware.py @@ -35,12 +35,16 @@ def __init__(self, get_response): self.get_response = get_response def __call__(self, request): - assert hasattr(request, "user"), "The Login Required middleware\ - requires authentication middleware to be installed. Edit your\ - MIDDLEWARE_CLASSES setting to insert\ - 'django.contrib.auth.middleware.AuthenticationMiddleware'. If that doesn't\ - work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes\ - 'django.core.context_processors.auth'." + if not hasattr(request, "user"): + msg = ( + "The Login Required middleware " + "requires authentication middleware to be installed. Edit your " + "MIDDLEWARE_CLASSES setting to insert " + "'django.contrib.auth.middleware.AuthenticationMiddleware'. If that doesn't " + "work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes " + "'django.core.context_processors.auth'." + ) + raise AttributeError(msg) if not request.user.is_authenticated: path = request.path_info.lstrip("/") if not any(m.match(path) for m in EXEMPT_URLS): diff --git a/ruff.toml b/ruff.toml index ac0f0ece1e..0f3ede2f2c 100644 --- a/ruff.toml +++ b/ruff.toml @@ -41,7 +41,7 @@ select = [ "UP", "YTT", "ASYNC", - "S2", "S5", "S7", + "S101", "S2", "S5", "S7", "FBT001", "FBT003", "A003", "A004", "A006", "COM", diff --git a/tests/Import_scanner_test.py b/tests/Import_scanner_test.py index b1597e9583..3006393aec 100644 --- a/tests/Import_scanner_test.py +++ b/tests/Import_scanner_test.py @@ -54,7 +54,7 @@ def test_check_test_file(self): logger.info("https://github.com/DefectDojo/sample-scan-files\n") for test in missing_tests: logger.info(test) - assert len(missing_tests) == 0 + self.assertEqual(len(missing_tests), 0) def test_check_for_forms(self): forms_path = dir_path[:-5] + "dojo/forms.py" @@ -91,7 +91,7 @@ def test_check_for_forms(self): logger.info("https://github.com/DefectDojo/django-DefectDojo/blob/master/dojo/forms.py\n") for tool in missing_forms: logger.info(tool) - assert len(missing_forms) == 0 + self.assertEqual(len(missing_forms), 0) @unittest.skip("Deprecated since Dynamic Parser infrastructure") def test_check_for_options(self): @@ -131,7 +131,7 @@ def test_check_for_options(self): logger.info("https://github.com/DefectDojo/django-DefectDojo/blob/master/dojo/templates/dojo/import_scan_results.html\n") for tool in missing_templates: logger.info(tool) - assert len(missing_templates) == 0 + self.assertEqual(len(missing_templates), 0) def test_engagement_import_scan_result(self): driver = self.driver @@ -216,7 +216,7 @@ def test_engagement_import_scan_result(self): logger.info("https://github.com/DefectDojo/sample-scan-files\n") for test in failed_tests: logger.info(test) - assert len(failed_tests) == 0 + self.assertEqual(len(failed_tests), 0) def tearDown(self): super().tearDown(self) diff --git a/tests/notifications_test.py b/tests/notifications_test.py index e64527cec9..d71067ce68 100644 --- a/tests/notifications_test.py +++ b/tests/notifications_test.py @@ -41,11 +41,13 @@ def test_disable_personal_notification(self): self.disable_notification() driver.get(self.base_url + "notifications") + in_place = False try: driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") - assert False + in_place = True except NoSuchElementException: - assert True + in_place = False + self.assertFalse(in_place) def test_enable_personal_notification(self): # Login to the site. Password will have to be modified @@ -56,13 +58,9 @@ def test_enable_personal_notification(self): driver.get(self.base_url + "notifications") try: driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") - assert True except NoSuchElementException: - if self.type == "msteams": - # msteam should be not in personal notifications - assert True - else: - assert False + # msteam should be not in personal notifications + self.assertEqual(self.type, "msteams") def test_disable_system_notification(self): # Login to the site. Password will have to be modified @@ -72,11 +70,13 @@ def test_disable_system_notification(self): self.disable_notification() driver.get(self.base_url + "notifications/system") + in_place = False try: driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") - assert False + in_place = True except NoSuchElementException: - assert True + in_place = False + self.assertFalse(in_place) def test_enable_system_notification(self): # Login to the site. Password will have to be modified @@ -84,12 +84,13 @@ def test_enable_system_notification(self): driver = self.driver self.enable_notification() - driver.get(self.base_url + "notifications/system") + in_place = False try: driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") - assert True + in_place = True except NoSuchElementException: - assert False + in_place = False + self.assertFalse(in_place) def test_disable_template_notification(self): # Login to the site. Password will have to be modified @@ -99,11 +100,13 @@ def test_disable_template_notification(self): self.disable_notification() driver.get(self.base_url + "notifications/template") + in_place = False try: driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") - assert False + in_place = True except NoSuchElementException: - assert True + in_place = False + self.assertFalse(in_place) def test_enable_template_notification(self): # Login to the site. Password will have to be modified @@ -114,13 +117,9 @@ def test_enable_template_notification(self): driver.get(self.base_url + "notifications/template") try: driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") - assert True except NoSuchElementException: - if self.type == "msteams": - # msteam should be not in personal notifications - assert True - else: - assert False + # msteam should be not in personal notifications + self.assertEqual(self.type, "msteams") def test_user_mail_notifications_change(self): # Login to the site. Password will have to be modified diff --git a/unittests/test_rest_framework.py b/unittests/test_rest_framework.py index 4021efc121..8b2c75e762 100644 --- a/unittests/test_rest_framework.py +++ b/unittests/test_rest_framework.py @@ -342,7 +342,8 @@ def _check(schema, obj): self._errors = [] self._prefix = [] _check(schema, obj) - assert not self._has_failed, "\n" + "\n".join(self._errors) + "\nFailed with " + str(len(self._errors)) + " errors" + if self._has_failed: + raise AssertionError("\n" + "\n".join(self._errors) + "\nFailed with " + str(len(self._errors)) + " errors") class TestType(Enum): @@ -1207,15 +1208,15 @@ def test_duplicate(self): result = self.client.get(self.url + "2/") self.assertEqual(result.status_code, status.HTTP_200_OK, "Could not check new duplicate") result_json = result.json() - assert result_json["duplicate"] - assert result_json["duplicate_finding"] == 3 + self.assertTrue(result_json["duplicate"]) + self.assertEqual(result_json["duplicate_finding"], 3) # Check duplicate status result = self.client.get(self.url + "3/duplicate/") - assert result.status_code == status.HTTP_200_OK, "Could not check duplicate status" + self.assertEqual(result.status_code, status.HTTP_200_OK, "Could not check duplicate status") result_json = result.json() # Should return all duplicates for id=3 - assert set(x["id"] for x in result_json) == {2, 4, 5, 6} # noqa: C401 + self.assertEqual({x["id"] for x in result_json}, {2, 4, 5, 6}) # Reset duplicate result = self.client.post(self.url + "2/duplicate/reset/") @@ -1223,44 +1224,44 @@ def test_duplicate(self): new_result = self.client.get(self.url + "2/") self.assertEqual(result.status_code, status.HTTP_204_NO_CONTENT, "Could not check reset duplicate status") result_json = new_result.json() - assert not result_json["duplicate"] - assert result_json["duplicate_finding"] is None + self.assertFalse(result_json["duplicate"]) + self.assertIsNone(result_json["duplicate_finding"]) def test_filter_steps_to_reproduce(self): # Confirm initial data result = self.client.get(self.url + "?steps_to_reproduce=lorem") self.assertEqual(result.status_code, status.HTTP_200_OK, "Could not filter on steps_to_reproduce") result_json = result.json() - assert result_json["count"] == 0 + self.assertEqual(result_json["count"], 0) # Set steps to reproduce result = self.client.patch(self.url + "2/", data={"steps_to_reproduce": "Lorem ipsum dolor sit amet"}) self.assertEqual(result.status_code, status.HTTP_200_OK, "Could not patch finding with steps to reproduce") - assert result.json()["steps_to_reproduce"] == "Lorem ipsum dolor sit amet" + self.assertEqual(result.json()["steps_to_reproduce"], "Lorem ipsum dolor sit amet") result = self.client.patch(self.url + "3/", data={"steps_to_reproduce": "Ut enim ad minim veniam"}) self.assertEqual(result.status_code, status.HTTP_200_OK, "Could not patch finding with steps to reproduce") - assert result.json()["steps_to_reproduce"] == "Ut enim ad minim veniam" + self.assertEqual(result.json()["steps_to_reproduce"], "Ut enim ad minim veniam") # Test result = self.client.get(self.url + "?steps_to_reproduce=lorem") self.assertEqual(result.status_code, status.HTTP_200_OK, "Could not filter on steps_to_reproduce") result_json = result.json() - assert result_json["count"] == 1 - assert result_json["results"][0]["id"] == 2 - assert result_json["results"][0]["steps_to_reproduce"] == "Lorem ipsum dolor sit amet" + self.assertEqual(result_json["count"], 1) + self.assertEqual(result_json["results"][0]["id"], 2) + self.assertEqual(result_json["results"][0]["steps_to_reproduce"], "Lorem ipsum dolor sit amet") # Set steps to reproduce result = self.client.patch(self.url + "2/", data={"steps_to_reproduce": ""}) self.assertEqual(result.status_code, status.HTTP_200_OK, "Could not patch finding with steps to reproduce") - assert result.json()["steps_to_reproduce"] == "" + self.assertEqual(result.json()["steps_to_reproduce"], "") result = self.client.patch(self.url + "3/", data={"steps_to_reproduce": ""}) self.assertEqual(result.status_code, status.HTTP_200_OK, "Could not patch finding with steps to reproduce") - assert result.json()["steps_to_reproduce"] == "" + self.assertEqual(result.json()["steps_to_reproduce"], "") def test_severity_validation(self): result = self.client.patch(self.url + "2/", data={"severity": "Not a valid choice"}) self.assertEqual(result.status_code, status.HTTP_400_BAD_REQUEST, "Severity just got set to something invalid") - assert result.json()["severity"] == ["Severity must be one of the following: ['Info', 'Low', 'Medium', 'High', 'Critical']"] + self.assertEqual(result.json()["severity"], ["Severity must be one of the following: ['Info', 'Low', 'Medium', 'High', 'Critical']"]) class FindingMetadataTest(BaseClass.BaseClassTest): @@ -1295,33 +1296,38 @@ def test_create(self): self.assertEqual(200, response.status_code, response.data) results = self.client.get(self.base_url).data + correct = False for result in results: if result["name"] == "test_meta2" and result["value"] == "40": + correct = True return - assert False, "Metadata was not created correctly" + self.assertTrue(correct, "Metadata was not created correctly") def test_create_duplicate(self): result = self.client.post(self.base_url, data={"name": "test_meta", "value": "40"}) - assert result.status_code == status.HTTP_400_BAD_REQUEST, "Metadata creation did not failed on duplicate" + self.assertEqual(result.status_code, status.HTTP_400_BAD_REQUEST, "Metadata creation did not failed on duplicate") def test_get(self): results = self.client.get(self.base_url, format="json").data + correct = False for result in results: if result["name"] == "test_meta" and result["value"] == "20": + correct = True return - assert False, "Metadata was not created correctly" + self.assertTrue(correct, "Metadata was not created correctly") def test_update(self): self.client.put(self.base_url + "?name=test_meta", data={"name": "test_meta", "value": "40"}) result = self.client.get(self.base_url).data[0] - assert result["name"] == "test_meta" and result["value"] == "40", "Metadata not edited correctly" + self.assertEqual(result["name"], "test_meta", "Metadata not edited correctly") + self.assertEqual(result["value"], "40", "Metadata not edited correctly") def test_delete(self): self.client.delete(self.base_url + "?name=test_meta") result = self.client.get(self.base_url).data - assert len(result) == 0, "Metadata not deleted correctly" + self.assertEqual(len(result), 0, "Metadata not deleted correctly") class FindingTemplatesTest(BaseClass.BaseClassTest): @@ -1543,7 +1549,7 @@ def __init__(self, *args, **kwargs): def test_severity_validation(self): result = self.client.patch(self.url + "2/", data={"severity": "Not a valid choice"}) self.assertEqual(result.status_code, status.HTTP_400_BAD_REQUEST, "Severity just got set to something invalid") - assert result.json()["severity"] == ["Severity must be one of the following: ['Info', 'Low', 'Medium', 'High', 'Critical']"] + self.assertEqual(result.json()["severity"], ["Severity must be one of the following: ['Info', 'Low', 'Medium', 'High', 'Critical']"]) class TestsTest(BaseClass.BaseClassTest):