Skip to content

Commit 129fddf

Browse files
cvssv3: backport tests (#12457)
1 parent ccf049f commit 129fddf

File tree

4 files changed

+202
-2
lines changed

4 files changed

+202
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pip-delete-this-directory.txt
4141
.ruff_cache
4242
nosetests.xml
4343
coverage.xml
44+
selenium_page_source.html
4445

4546
# Translations
4647
*.mo

tests/finding_test.py

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ def test_edit_finding(self):
115115
# Change: 'Severity' and 'cvssv3'
116116
# finding Severity
117117
Select(driver.find_element(By.ID, "id_severity")).select_by_visible_text("Critical")
118-
# cvssv3
119-
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")
120118
# finding Vulnerability Ids
121119
driver.find_element(By.ID, "id_vulnerability_ids").send_keys("\nREF-3\nREF-4\n")
122120
# "Click" the Done button to Edit the finding
@@ -131,6 +129,96 @@ def test_edit_finding(self):
131129
self.assertTrue(self.is_text_present_on_page(text="REF-4"))
132130
self.assertTrue(self.is_text_present_on_page(text="Additional Vulnerability Ids"))
133131

132+
def _edit_finding_cvssv3_and_assert(
133+
self,
134+
cvssv3_value,
135+
cvssv3_score,
136+
expected_cvssv3_value,
137+
expected_cvssv3_score,
138+
expect_success=True, # noqa: FBT002
139+
success_message="Finding saved successfully",
140+
error_message=None,
141+
):
142+
driver = self.driver
143+
# Navigate to All Finding page
144+
self.goto_all_findings_list(driver)
145+
# Select and click on the particular finding to edit
146+
driver.find_element(By.LINK_TEXT, "App Vulnerable to XSS").click()
147+
# Click on the 'dropdownMenu1 button'
148+
driver.find_element(By.ID, "dropdownMenu1").click()
149+
# Click on `Edit Finding`
150+
driver.find_element(By.LINK_TEXT, "Edit Finding").click()
151+
# Set cvssv3 value and score
152+
driver.find_element(By.ID, "id_cvssv3").clear()
153+
driver.find_element(By.ID, "id_cvssv3").send_keys(cvssv3_value)
154+
driver.find_element(By.ID, "id_cvssv3_score").clear()
155+
driver.find_element(By.ID, "id_cvssv3_score").send_keys(str(cvssv3_score))
156+
# Submit the form
157+
driver.find_element(By.XPATH, "//input[@name='_Finished']").click()
158+
159+
if expect_success:
160+
self.assertTrue(self.is_success_message_present(text=success_message))
161+
# Go into edit mode again to check stored values
162+
driver.find_element(By.ID, "dropdownMenu1").click()
163+
driver.find_element(By.LINK_TEXT, "Edit Finding").click()
164+
self.assertEqual(expected_cvssv3_value, driver.find_element(By.ID, "id_cvssv3").get_attribute("value"))
165+
self.assertEqual(str(expected_cvssv3_score), driver.find_element(By.ID, "id_cvssv3_score").get_attribute("value"))
166+
else:
167+
self.assertTrue(self.is_error_message_present(text=error_message))
168+
169+
# See https://github.com/DefectDojo/django-DefectDojo/issues/8264
170+
# Capturing current behavior which might not be the desired one yet
171+
@on_exception_html_source_logger
172+
def test_edit_finding_cvssv3_valid_vector(self):
173+
self._edit_finding_cvssv3_and_assert(
174+
cvssv3_value="CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
175+
cvssv3_score="1",
176+
expected_cvssv3_value="CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
177+
expected_cvssv3_score="8.8",
178+
expect_success=True,
179+
)
180+
181+
@on_exception_html_source_logger
182+
def test_edit_finding_cvssv3_valid_vector_no_prefix(self):
183+
self._edit_finding_cvssv3_and_assert(
184+
cvssv3_value="AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
185+
cvssv3_score="2",
186+
expected_cvssv3_value="AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
187+
expected_cvssv3_score="2.0",
188+
expect_success=True,
189+
)
190+
191+
@on_exception_html_source_logger
192+
def test_edit_finding_cvssv3_valid_vector_with_trailing_slash(self):
193+
self._edit_finding_cvssv3_and_assert(
194+
cvssv3_value="CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/",
195+
cvssv3_score="3",
196+
expected_cvssv3_value="CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/",
197+
expected_cvssv3_score="3.0",
198+
expect_success=True,
199+
)
200+
201+
@on_exception_html_source_logger
202+
def test_edit_finding_cvssv3_with_v2_vector(self):
203+
self._edit_finding_cvssv3_and_assert(
204+
cvssv3_value="CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P",
205+
cvssv3_score="4",
206+
expected_cvssv3_value="CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P",
207+
expected_cvssv3_score="4.0",
208+
expect_success=True,
209+
)
210+
211+
@on_exception_html_source_logger
212+
def test_edit_finding_cvssv3_with_rubbish(self):
213+
self._edit_finding_cvssv3_and_assert(
214+
cvssv3_value="happy little vector",
215+
cvssv3_score="4",
216+
expected_cvssv3_value=None,
217+
expected_cvssv3_score=None,
218+
expect_success=False,
219+
error_message="CVSS must be entered in format: 'AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H'",
220+
)
221+
134222
def test_add_image(self):
135223
# The Name of the Finding created by test_add_product_finding => 'App Vulnerable to XSS'
136224
# Test To Add Finding To product
@@ -519,6 +607,11 @@ def add_finding_tests_to_suite(suite, *, jira=False, github=False, block_executi
519607
suite.addTest(FindingTest("test_excel_export"))
520608
suite.addTest(FindingTest("test_list_components"))
521609
suite.addTest(FindingTest("test_edit_finding"))
610+
suite.addTest(FindingTest("test_edit_finding_cvssv3_valid_vector"))
611+
suite.addTest(FindingTest("test_edit_finding_cvssv3_valid_vector_no_prefix"))
612+
suite.addTest(FindingTest("test_edit_finding_cvssv3_valid_vector_with_trailing_slash"))
613+
suite.addTest(FindingTest("test_edit_finding_cvssv3_with_v2_vector"))
614+
suite.addTest(FindingTest("test_edit_finding_cvssv3_with_rubbish"))
522615
suite.addTest(FindingTest("test_add_note_to_finding"))
523616
suite.addTest(FindingTest("test_add_image"))
524617
suite.addTest(FindingTest("test_delete_image"))

unittests/test_finding_model.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99

1010
class TestFindingModel(DojoTestCase):
11+
fixtures = ["dojo_testdata.json"]
1112

1213
def test_get_sast_source_file_path_with_link_no_file_path(self):
1314
finding = Finding()
@@ -315,6 +316,47 @@ def test_get_references_with_links_markdown(self):
315316
finding.references = "URL: [https://www.example.com](https://www.example.com)"
316317
self.assertEqual("URL: [https://www.example.com](https://www.example.com)", finding.get_references_with_links())
317318

319+
# See https://github.com/DefectDojo/django-DefectDojo/issues/8264
320+
# Capturing current behavior which might not be the desired one yet
321+
def test_cvssv3(self):
322+
"""Tests if the CVSSv3 score is calculated correctly"""
323+
user, _ = User.objects.get_or_create(username="admin")
324+
product_type = self.create_product_type("test_product_type")
325+
product = self.create_product(name="test_product", prod_type=product_type)
326+
engagement = self.create_engagement("test_eng", product)
327+
test = self.create_test(engagement=engagement, scan_type="ZAP Scan", title="test_test")
328+
finding = Finding.objects.create(
329+
test=test,
330+
reporter=user,
331+
title="test_finding",
332+
severity="Critical",
333+
date=datetime.now().date())
334+
finding.cvssv3 = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
335+
finding.save()
336+
337+
self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H")
338+
self.assertEqual(finding.cvssv3_score, 9.8)
339+
finding_id = finding.id
340+
341+
finding = Finding.objects.get(id=finding_id)
342+
finding.cvssv3 = "AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"
343+
finding.save()
344+
345+
self.assertEqual(finding.cvssv3, "AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H")
346+
# invalid vector, so score still 9.8 from previous save (and not 8.8)
347+
self.assertEqual(finding.cvssv3_score, 9.8)
348+
349+
finding = Finding.objects.get(id=finding_id)
350+
finding.cvssv3 = "happy little vector"
351+
finding.save()
352+
353+
self.assertEqual(finding.cvssv3, "happy little vector")
354+
# invalid vector, so score still 9.8 from previous save
355+
self.assertEqual(finding.cvssv3_score, 9.8)
356+
357+
# we already have more cvssv3 test in test_rest_framework.py and finding_test.py
358+
# the above here only shows that invalid vectors can be saved
359+
318360

319361
class TestFindingSLAExpiration(DojoTestCase):
320362
fixtures = ["dojo_testdata.json"]

unittests/test_rest_framework.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,70 @@ def test_severity_validation(self):
12811281
self.assertEqual(result.status_code, status.HTTP_400_BAD_REQUEST, "Severity just got set to something invalid")
12821282
self.assertEqual(result.json()["severity"], ["Severity must be one of the following: ['Info', 'Low', 'Medium', 'High', 'Critical']"])
12831283

1284+
# See https://github.com/DefectDojo/django-DefectDojo/issues/8264
1285+
# Capturing current behavior which might not be the desired one yet
1286+
def test_cvss3_validation(self):
1287+
with self.subTest(i=0):
1288+
self.assertEqual(None, Finding.objects.get(id=2).cvssv3)
1289+
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})
1290+
self.assertEqual(result.status_code, status.HTTP_200_OK)
1291+
finding = Finding.objects.get(id=2)
1292+
self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3)
1293+
self.assertEqual(8.8, finding.cvssv3_score)
1294+
1295+
with self.subTest(i=1):
1296+
# extra slash makes it invalid
1297+
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})
1298+
self.assertEqual(result.status_code, status.HTTP_200_OK)
1299+
finding = Finding.objects.get(id=3)
1300+
self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/", finding.cvssv3)
1301+
self.assertEqual(3, finding.cvssv3_score)
1302+
1303+
with self.subTest(i=2):
1304+
# no CVSS version prefix makes it invalid
1305+
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})
1306+
self.assertEqual(result.status_code, status.HTTP_200_OK)
1307+
finding = Finding.objects.get(id=3)
1308+
self.assertEqual("AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3)
1309+
# invalid vector, so no calculated score
1310+
self.assertEqual(4, finding.cvssv3_score)
1311+
1312+
with self.subTest(i=3):
1313+
# CVSS4 version makes it invalid
1314+
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})
1315+
self.assertEqual(result.status_code, status.HTTP_200_OK)
1316+
finding = Finding.objects.get(id=3)
1317+
self.assertEqual("CVSS:4.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3)
1318+
# invalid vector, so no calculated score
1319+
self.assertEqual(5, finding.cvssv3_score)
1320+
1321+
with self.subTest(i=4):
1322+
# CVSS2 style vector makes not supported
1323+
result = self.client.patch(self.url + "3/", data={"cvssv3": "AV:N/AC:L/Au:N/C:P/I:P/A:P", "cvssv3_score": 6})
1324+
self.assertEqual(result.status_code, status.HTTP_200_OK)
1325+
finding = Finding.objects.get(id=3)
1326+
self.assertEqual("AV:N/AC:L/Au:N/C:P/I:P/A:P", finding.cvssv3)
1327+
# invalid vector, so no calculated score
1328+
self.assertEqual(6, finding.cvssv3_score)
1329+
1330+
with self.subTest(i=5):
1331+
# CVSS2 prefix makes it invalid
1332+
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})
1333+
self.assertEqual(result.status_code, status.HTTP_200_OK)
1334+
finding = Finding.objects.get(id=3)
1335+
self.assertEqual("CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P", finding.cvssv3)
1336+
# invalid vector, so no calculated score
1337+
self.assertEqual(7, finding.cvssv3_score)
1338+
1339+
with self.subTest(i=6):
1340+
# try to put rubbish in there
1341+
result = self.client.patch(self.url + "4/", data={"cvssv3": "happy little vector", "cvssv3_score": 3})
1342+
self.assertEqual(result.status_code, status.HTTP_400_BAD_REQUEST)
1343+
finding = Finding.objects.get(id=4)
1344+
self.assertEqual(None, finding.cvssv3)
1345+
# invalid request, so no score at all
1346+
self.assertEqual(None, finding.cvssv3_score)
1347+
12841348

12851349
class FindingMetadataTest(BaseClass.BaseClassTest):
12861350
fixtures = ["dojo_testdata.json"]

0 commit comments

Comments
 (0)