Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ This will open the **Edit Finding** form, where you can edit the metadata, chang
* **SAST / DAST** are labels used to organize your Findings into the context they were discovered in. Generally, this label is populated based on the scanning tool used, but you can adjust this to a more accurate level (for example, if the Finding was found by both a SAST and a DAST tool).

### Editing the Mitigated Date and Mitigated By

By default, a Finding's **Mitigated Date** and **Mitigated By** values are **not editable**. These fields are hidden from both the Edit Finding form and the Close Finding dialog, and the Mitigated Date is always set automatically to the moment the Finding is closed. Attempting to set or backdate these values through the API is rejected for the same reason.

Editing can be turned on with the `DD_EDITABLE_MITIGATED_DATA` server setting. When it is enabled, the **Mitigated Date** and **Mitigated By** fields appear in the Edit Finding form and the Close Finding dialog, and can also be set through the API — but only for users with **superuser** status. In other words, editing requires *both* the setting to be enabled *and* the acting user to be a superuser.

* **Why it's off by default:** allowing a mitigation to be backdated can misrepresent SLA compliance — a Finding that was actually remediated *outside* its SLA window could be recorded as though it had been mitigated *within* SLA. Enabling the setting is forward-looking only; it does **not** change the Mitigated Date or age of any existing Findings.
* **Everything stays auditable:** every change to a Finding, including edits to the Mitigated Date and Mitigated By, is captured in the Finding's history log — who made the change, when, and the previous and new values.
* **Applying the setting:** `DD_EDITABLE_MITIGATED_DATA` is a server-level environment variable (see [Configuration](/get_started/open_source/configuration/)). Changing it requires a service restart to take effect.
* **DefectDojo Cloud / Pro:** this setting cannot be changed from the UI. Contact DefectDojo Support to have it enabled for your instance.

## Bulk Edit Findings

Findings can be edited in bulk from a Finding List, which can be found either on the Findings page itself, or from within a Test.
Expand Down
5 changes: 5 additions & 0 deletions dojo/finding/ui/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,11 @@ def __init__(self, *args, **kwargs):
self.fields["mitigated_by"].queryset = get_authorized_users("edit")
self.fields["mitigated"].initial = self.instance.mitigated
self.fields["mitigated_by"].initial = self.instance.mitigated_by
else:
# mitigated data is not editable: hide the fields so users are not
# presented with inputs whose values would be silently ignored
del self.fields["mitigated"]
del self.fields["mitigated_by"]
if disclaimer := get_system_setting("disclaimer_notes"):
self.disclaimer = disclaimer.strip()

Expand Down
5 changes: 4 additions & 1 deletion dojo/settings/settings.dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,10 @@
# we limit the amount of duplicates that can be deleted in a single run of that job
# to prevent overlapping runs of that job from occurrring
DD_DUPE_DELETE_MAX_PER_RUN=(int, 200),
# when enabled 'mitigated date' and 'mitigated by' of a finding become editable
# When enabled, superusers can edit a finding's 'mitigated date' and 'mitigated by'
# fields (e.g. backdate a mitigation) from both the UI and the API. Off by default
# because backdating a mitigation can distort SLA-compliance metrics. Changing this
# value requires a service restart to take effect.
DD_EDITABLE_MITIGATED_DATA=(bool, False),
# new feature that tracks history across multiple reimports for the same test
DD_TRACK_IMPORT_HISTORY=(bool, True),
Expand Down
62 changes: 62 additions & 0 deletions unittests/test_system_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,68 @@ def test_post_request_initializes_form_with_finding_instance(self):
self.assertIn(response.status_code, [200, 302])


@override_settings(DD_EDITABLE_MITIGATED_DATA=False)
class CloseFindingViewMitigatedDataDisabledTest(TestCase):

"""
When DD_EDITABLE_MITIGATED_DATA is disabled (the default), the Close Finding
form must not expose the mitigated/mitigated_by fields, and any mitigated value
supplied in the payload must be ignored so the finding is closed with the
current date rather than a backdated one.
"""

def setUp(self):
self.user = User.objects.create_user(
username="tester-mitigated-disabled",
password="pass", # noqa: S106
is_staff=True,
is_superuser=True,
)
self.client.force_login(self.user)
self.product_type = Product_Type.objects.create(name="Disabled Product Type")
self.product = Product.objects.create(name="Disabled Product", description="test", prod_type=self.product_type)
self.engagement = Engagement.objects.create(
name="Disabled Engagement",
product=self.product,
target_start=now(),
target_end=now(),
)
self.test_type = Test_Type.objects.create(name="Disabled Unit Test Type")
self.test = Test.objects.create(
engagement=self.engagement,
test_type=self.test_type,
title="Test for Finding",
target_start=now(),
target_end=now(),
)
self.finding = Finding.objects.create(
title="Close Finding Disabled Test",
active=True,
test=self.test,
reporter=self.user,
)
self.url = reverse("close_finding", args=[self.finding.id])

def test_close_form_hides_mitigated_fields(self):
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
form = response.context["form"]
self.assertNotIn("mitigated", form.fields)
self.assertNotIn("mitigated_by", form.fields)

def test_backdated_mitigated_is_ignored(self):
response = self.client.post(
self.url,
{"entry": "Closing this finding", "mitigated": "2020-01-01"},
)
self.assertEqual(response.status_code, 302)
self.finding.refresh_from_db()
self.assertTrue(self.finding.is_mitigated)
self.assertIsNotNone(self.finding.mitigated)
# the backdated value must be ignored: mitigation date is "now", not 2020
self.assertEqual(self.finding.mitigated.year, now().year)


class TestSystemSettingsMiddlewareIntegration(DojoTestCase):

"""Integration tests for DojoSytemSettingsMiddleware using RequestFactory."""
Expand Down
Loading