Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pip-delete-this-directory.txt
.ruff_cache
nosetests.xml
coverage.xml
selenium_page_source.html

# Translations
*.mo
Expand Down
97 changes: 95 additions & 2 deletions tests/finding_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,6 @@ def test_edit_finding(self):
# Change: 'Severity' and 'cvssv3'
# finding Severity
Select(driver.find_element(By.ID, "id_severity")).select_by_visible_text("Critical")
# cvssv3
driver.find_element(By.ID, "id_cvssv3").send_keys("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H")
# finding Vulnerability Ids
driver.find_element(By.ID, "id_vulnerability_ids").send_keys("\nREF-3\nREF-4\n")
# "Click" the Done button to Edit the finding
Expand All @@ -131,6 +129,96 @@ def test_edit_finding(self):
self.assertTrue(self.is_text_present_on_page(text="REF-4"))
self.assertTrue(self.is_text_present_on_page(text="Additional Vulnerability Ids"))

def _edit_finding_cvssv3_and_assert(
self,
cvssv3_value,
cvssv3_score,
expected_cvssv3_value,
expected_cvssv3_score,
expect_success=True, # noqa: FBT002
success_message="Finding saved successfully",
error_message=None,
):
driver = self.driver
# Navigate to All Finding page
self.goto_all_findings_list(driver)
# Select and click on the particular finding to edit
driver.find_element(By.LINK_TEXT, "App Vulnerable to XSS").click()
# Click on the 'dropdownMenu1 button'
driver.find_element(By.ID, "dropdownMenu1").click()
# Click on `Edit Finding`
driver.find_element(By.LINK_TEXT, "Edit Finding").click()
# Set cvssv3 value and score
driver.find_element(By.ID, "id_cvssv3").clear()
driver.find_element(By.ID, "id_cvssv3").send_keys(cvssv3_value)
driver.find_element(By.ID, "id_cvssv3_score").clear()
driver.find_element(By.ID, "id_cvssv3_score").send_keys(str(cvssv3_score))
# Submit the form
driver.find_element(By.XPATH, "//input[@name='_Finished']").click()

if expect_success:
self.assertTrue(self.is_success_message_present(text=success_message))
# Go into edit mode again to check stored values
driver.find_element(By.ID, "dropdownMenu1").click()
driver.find_element(By.LINK_TEXT, "Edit Finding").click()
self.assertEqual(expected_cvssv3_value, driver.find_element(By.ID, "id_cvssv3").get_attribute("value"))
self.assertEqual(str(expected_cvssv3_score), driver.find_element(By.ID, "id_cvssv3_score").get_attribute("value"))
else:
self.assertTrue(self.is_error_message_present(text=error_message))

# See https://github.com/DefectDojo/django-DefectDojo/issues/8264
# Capturing current behavior which might not be the desired one yet
@on_exception_html_source_logger
def test_edit_finding_cvssv3_valid_vector(self):
self._edit_finding_cvssv3_and_assert(
cvssv3_value="CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
cvssv3_score="1",
expected_cvssv3_value="CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
expected_cvssv3_score="8.8",
expect_success=True,
)

@on_exception_html_source_logger
def test_edit_finding_cvssv3_valid_vector_no_prefix(self):
self._edit_finding_cvssv3_and_assert(
cvssv3_value="AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
cvssv3_score="2",
expected_cvssv3_value="AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
expected_cvssv3_score="2.0",
expect_success=True,
)

@on_exception_html_source_logger
def test_edit_finding_cvssv3_valid_vector_with_trailing_slash(self):
self._edit_finding_cvssv3_and_assert(
cvssv3_value="CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/",
cvssv3_score="3",
expected_cvssv3_value="CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/",
expected_cvssv3_score="3.0",
expect_success=True,
)

@on_exception_html_source_logger
def test_edit_finding_cvssv3_with_v2_vector(self):
self._edit_finding_cvssv3_and_assert(
cvssv3_value="CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P",
cvssv3_score="4",
expected_cvssv3_value="CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P",
expected_cvssv3_score="4.0",
expect_success=True,
)

@on_exception_html_source_logger
def test_edit_finding_cvssv3_with_rubbish(self):
self._edit_finding_cvssv3_and_assert(
cvssv3_value="happy little vector",
cvssv3_score="4",
expected_cvssv3_value=None,
expected_cvssv3_score=None,
expect_success=False,
error_message="CVSS must be entered in format: 'AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H'",
)

def test_add_image(self):
# The Name of the Finding created by test_add_product_finding => 'App Vulnerable to XSS'
# Test To Add Finding To product
Expand Down Expand Up @@ -519,6 +607,11 @@ def add_finding_tests_to_suite(suite, *, jira=False, github=False, block_executi
suite.addTest(FindingTest("test_excel_export"))
suite.addTest(FindingTest("test_list_components"))
suite.addTest(FindingTest("test_edit_finding"))
suite.addTest(FindingTest("test_edit_finding_cvssv3_valid_vector"))
suite.addTest(FindingTest("test_edit_finding_cvssv3_valid_vector_no_prefix"))
suite.addTest(FindingTest("test_edit_finding_cvssv3_valid_vector_with_trailing_slash"))
suite.addTest(FindingTest("test_edit_finding_cvssv3_with_v2_vector"))
suite.addTest(FindingTest("test_edit_finding_cvssv3_with_rubbish"))
suite.addTest(FindingTest("test_add_note_to_finding"))
suite.addTest(FindingTest("test_add_image"))
suite.addTest(FindingTest("test_delete_image"))
Expand Down
42 changes: 42 additions & 0 deletions unittests/test_finding_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@


class TestFindingModel(DojoTestCase):
fixtures = ["dojo_testdata.json"]

def test_get_sast_source_file_path_with_link_no_file_path(self):
finding = Finding()
Expand Down Expand Up @@ -315,6 +316,47 @@ def test_get_references_with_links_markdown(self):
finding.references = "URL: [https://www.example.com](https://www.example.com)"
self.assertEqual("URL: [https://www.example.com](https://www.example.com)", finding.get_references_with_links())

# See https://github.com/DefectDojo/django-DefectDojo/issues/8264
# Capturing current behavior which might not be the desired one yet
def test_cvssv3(self):
"""Tests if the CVSSv3 score is calculated correctly"""
user, _ = User.objects.get_or_create(username="admin")
product_type = self.create_product_type("test_product_type")
product = self.create_product(name="test_product", prod_type=product_type)
engagement = self.create_engagement("test_eng", product)
test = self.create_test(engagement=engagement, scan_type="ZAP Scan", title="test_test")
finding = Finding.objects.create(
test=test,
reporter=user,
title="test_finding",
severity="Critical",
date=datetime.now().date())
finding.cvssv3 = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
finding.save()

self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H")
self.assertEqual(finding.cvssv3_score, 9.8)
finding_id = finding.id

finding = Finding.objects.get(id=finding_id)
finding.cvssv3 = "AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"
finding.save()

self.assertEqual(finding.cvssv3, "AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H")
# invalid vector, so score still 9.8 from previous save (and not 8.8)
self.assertEqual(finding.cvssv3_score, 9.8)

finding = Finding.objects.get(id=finding_id)
finding.cvssv3 = "happy little vector"
finding.save()

self.assertEqual(finding.cvssv3, "happy little vector")
# invalid vector, so score still 9.8 from previous save
self.assertEqual(finding.cvssv3_score, 9.8)

# we already have more cvssv3 test in test_rest_framework.py and finding_test.py
# the above here only shows that invalid vectors can be saved


class TestFindingSLAExpiration(DojoTestCase):
fixtures = ["dojo_testdata.json"]
Expand Down
64 changes: 64 additions & 0 deletions unittests/test_rest_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,70 @@ def test_severity_validation(self):
self.assertEqual(result.status_code, status.HTTP_400_BAD_REQUEST, "Severity just got set to something invalid")
self.assertEqual(result.json()["severity"], ["Severity must be one of the following: ['Info', 'Low', 'Medium', 'High', 'Critical']"])

# See https://github.com/DefectDojo/django-DefectDojo/issues/8264
# Capturing current behavior which might not be the desired one yet
def test_cvss3_validation(self):
with self.subTest(i=0):
self.assertEqual(None, Finding.objects.get(id=2).cvssv3)
result = self.client.patch(self.url + "2/", data={"cvssv3": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "cvssv3_score": 3})
self.assertEqual(result.status_code, status.HTTP_200_OK)
finding = Finding.objects.get(id=2)
self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3)
self.assertEqual(8.8, finding.cvssv3_score)

with self.subTest(i=1):
# extra slash makes it invalid
result = self.client.patch(self.url + "3/", data={"cvssv3": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/", "cvssv3_score": 3})
self.assertEqual(result.status_code, status.HTTP_200_OK)
finding = Finding.objects.get(id=3)
self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/", finding.cvssv3)
self.assertEqual(3, finding.cvssv3_score)

with self.subTest(i=2):
# no CVSS version prefix makes it invalid
result = self.client.patch(self.url + "3/", data={"cvssv3": "AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "cvssv3_score": 4})
self.assertEqual(result.status_code, status.HTTP_200_OK)
finding = Finding.objects.get(id=3)
self.assertEqual("AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3)
# invalid vector, so no calculated score
self.assertEqual(4, finding.cvssv3_score)

with self.subTest(i=3):
# CVSS4 version makes it invalid
result = self.client.patch(self.url + "3/", data={"cvssv3": "CVSS:4.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "cvssv3_score": 5})
self.assertEqual(result.status_code, status.HTTP_200_OK)
finding = Finding.objects.get(id=3)
self.assertEqual("CVSS:4.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3)
# invalid vector, so no calculated score
self.assertEqual(5, finding.cvssv3_score)

with self.subTest(i=4):
# CVSS2 style vector makes not supported
result = self.client.patch(self.url + "3/", data={"cvssv3": "AV:N/AC:L/Au:N/C:P/I:P/A:P", "cvssv3_score": 6})
self.assertEqual(result.status_code, status.HTTP_200_OK)
finding = Finding.objects.get(id=3)
self.assertEqual("AV:N/AC:L/Au:N/C:P/I:P/A:P", finding.cvssv3)
# invalid vector, so no calculated score
self.assertEqual(6, finding.cvssv3_score)

with self.subTest(i=5):
# CVSS2 prefix makes it invalid
result = self.client.patch(self.url + "3/", data={"cvssv3": "CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P", "cvssv3_score": 7})
self.assertEqual(result.status_code, status.HTTP_200_OK)
finding = Finding.objects.get(id=3)
self.assertEqual("CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P", finding.cvssv3)
# invalid vector, so no calculated score
self.assertEqual(7, finding.cvssv3_score)

with self.subTest(i=6):
# try to put rubbish in there
result = self.client.patch(self.url + "4/", data={"cvssv3": "happy little vector", "cvssv3_score": 3})
self.assertEqual(result.status_code, status.HTTP_400_BAD_REQUEST)
finding = Finding.objects.get(id=4)
self.assertEqual(None, finding.cvssv3)
# invalid request, so no score at all
self.assertEqual(None, finding.cvssv3_score)


class FindingMetadataTest(BaseClass.BaseClassTest):
fixtures = ["dojo_testdata.json"]
Expand Down