Skip to content

Commit c135389

Browse files
finding_templates: remove automated matching logic
1 parent c948cfb commit c135389

11 files changed

Lines changed: 170 additions & 137 deletions
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Generated by Django migration
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("dojo", "0251_usercontactinfo_reset_timestamps"),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name="system_settings",
15+
name="enable_template_match",
16+
),
17+
migrations.RemoveField(
18+
model_name="finding_template",
19+
name="template_match",
20+
),
21+
migrations.RemoveField(
22+
model_name="finding_template",
23+
name="template_match_title",
24+
),
25+
]
26+
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Generated by Django 5.2.9 on 2025-12-20 18:37
2+
3+
import pgtrigger.compiler
4+
import pgtrigger.migrations
5+
from django.db import migrations
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('dojo', '0252_remove_template_match_fields'),
12+
]
13+
14+
operations = [
15+
pgtrigger.migrations.RemoveTrigger(
16+
model_name='finding_template',
17+
name='insert_insert',
18+
),
19+
pgtrigger.migrations.RemoveTrigger(
20+
model_name='finding_template',
21+
name='update_update',
22+
),
23+
pgtrigger.migrations.RemoveTrigger(
24+
model_name='finding_template',
25+
name='delete_delete',
26+
),
27+
migrations.RemoveField(
28+
model_name='finding_templateevent',
29+
name='template_match',
30+
),
31+
migrations.RemoveField(
32+
model_name='finding_templateevent',
33+
name='template_match_title',
34+
),
35+
pgtrigger.migrations.AddTrigger(
36+
model_name='finding_template',
37+
trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_finding_templateevent" ("cve", "cvssv3", "cwe", "description", "id", "impact", "last_used", "mitigation", "numerical_severity", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "refs", "severity", "title") VALUES (NEW."cve", NEW."cvssv3", NEW."cwe", NEW."description", NEW."id", NEW."impact", NEW."last_used", NEW."mitigation", NEW."numerical_severity", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."refs", NEW."severity", NEW."title"); RETURN NULL;', hash='e55723452b8a9b306119b9cbb20e7d798552dd45', operation='INSERT', pgid='pgtrigger_insert_insert_59092', table='dojo_finding_template', when='AFTER')),
38+
),
39+
pgtrigger.migrations.AddTrigger(
40+
model_name='finding_template',
41+
trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD.* IS DISTINCT FROM NEW.*)', func='INSERT INTO "dojo_finding_templateevent" ("cve", "cvssv3", "cwe", "description", "id", "impact", "last_used", "mitigation", "numerical_severity", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "refs", "severity", "title") VALUES (NEW."cve", NEW."cvssv3", NEW."cwe", NEW."description", NEW."id", NEW."impact", NEW."last_used", NEW."mitigation", NEW."numerical_severity", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."refs", NEW."severity", NEW."title"); RETURN NULL;', hash='eef457aa5665a449a8040e3a750a0b708714177a', operation='UPDATE', pgid='pgtrigger_update_update_43036', table='dojo_finding_template', when='AFTER')),
42+
),
43+
pgtrigger.migrations.AddTrigger(
44+
model_name='finding_template',
45+
trigger=pgtrigger.compiler.Trigger(name='delete_delete', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_finding_templateevent" ("cve", "cvssv3", "cwe", "description", "id", "impact", "last_used", "mitigation", "numerical_severity", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "refs", "severity", "title") VALUES (OLD."cve", OLD."cvssv3", OLD."cwe", OLD."description", OLD."id", OLD."impact", OLD."last_used", OLD."mitigation", OLD."numerical_severity", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."refs", OLD."severity", OLD."title"); RETURN NULL;', hash='ab2da63140c213dcf78cf413a69e1a2289a2fc3b', operation='DELETE', pgid='pgtrigger_delete_delete_3f3a6', table='dojo_finding_template', when='AFTER')),
46+
),
47+
]

dojo/finding/urls.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,6 @@
134134
views.clear_finding_review, name="clear_finding_review"),
135135
re_path(r"^finding/(?P<fid>\d+)/copy$",
136136
views.copy_finding, name="copy_finding"),
137-
re_path(r"^finding/(?P<fid>\d+)/apply_cwe$",
138-
views.apply_template_cwe, name="apply_template_cwe"),
139137
re_path(r"^finding/(?P<fid>\d+)/mktemplate$", views.mktemplate,
140138
name="mktemplate"),
141139
re_path(r"^finding/(?P<fid>\d+)/find_template_to_apply$", views.find_template_to_apply,

dojo/finding/views.py

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from django.db.models.query import Prefetch
2020
from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect, JsonResponse, StreamingHttpResponse
2121
from django.shortcuts import get_object_or_404, render
22-
from django.template.defaultfilters import pluralize
2322
from django.urls import reverse
2423
from django.utils import formats, timezone
2524
from django.utils.safestring import mark_safe
@@ -62,7 +61,6 @@
6261
EditPlannedRemediationDateFindingForm,
6362
FindingBulkUpdateForm,
6463
FindingForm,
65-
FindingFormID,
6664
FindingTemplateForm,
6765
GITHUBFindingForm,
6866
JIRAFindingForm,
@@ -111,7 +109,6 @@
111109
add_external_issue,
112110
add_field_errors_to_response,
113111
add_success_message_to_response,
114-
apply_cwe_to_template,
115112
calculate_grade,
116113
do_false_positive_history,
117114
get_page_items,
@@ -476,15 +473,6 @@ def get_credential_objects(self, finding: Finding):
476473
"cred_engagement": cred_engagement,
477474
}
478475

479-
def get_cwe_template(self, finding: Finding):
480-
cwe_template = None
481-
with contextlib.suppress(Finding_Template.DoesNotExist):
482-
cwe_template = Finding_Template.objects.filter(cwe=finding.cwe).first()
483-
484-
return {
485-
"cwe_template": cwe_template,
486-
}
487-
488476
def get_request_response(self, finding: Finding):
489477
request_response = None
490478
burp_request = None
@@ -695,7 +683,6 @@ def get(self, request: HttpRequest, finding_id: int):
695683
# Add in the other extras
696684
context |= self.get_previous_and_next_findings(finding)
697685
context |= self.get_credential_objects(finding)
698-
context |= self.get_cwe_template(finding)
699686
# Add in more of the other extras
700687
context |= self.get_request_response(finding)
701688
context |= self.get_similar_findings(request, finding)
@@ -1343,31 +1330,6 @@ def reopen_finding(request, fid):
13431330
return HttpResponseRedirect(reverse("view_finding", args=(finding.id,)))
13441331

13451332

1346-
@user_is_authorized(Finding, Permissions.Finding_Edit, "fid")
1347-
def apply_template_cwe(request, fid):
1348-
finding = get_object_or_404(Finding, id=fid)
1349-
if request.method == "POST":
1350-
form = FindingFormID(request.POST, instance=finding)
1351-
if form.is_valid():
1352-
finding = apply_cwe_to_template(finding)
1353-
finding.save()
1354-
messages.add_message(
1355-
request,
1356-
messages.SUCCESS,
1357-
"Finding CWE template applied successfully.",
1358-
extra_tags="alert-success",
1359-
)
1360-
return HttpResponseRedirect(reverse("view_finding", args=(fid,)))
1361-
messages.add_message(
1362-
request,
1363-
messages.ERROR,
1364-
"Unable to apply CWE template finding, please try again.",
1365-
extra_tags="alert-danger",
1366-
)
1367-
return None
1368-
raise PermissionDenied
1369-
1370-
13711333
@user_is_authorized(Finding, Permissions.Finding_Edit, "fid")
13721334
def copy_finding(request, fid):
13731335
finding = get_object_or_404(Finding, id=fid)
@@ -2246,7 +2208,6 @@ def add_template(request):
22462208
if request.method == "POST":
22472209
form = FindingTemplateForm(request.POST)
22482210
if form.is_valid():
2249-
apply_message = ""
22502211
template = form.save(commit=False)
22512212
template.numerical_severity = Finding.get_numerical_severity(
22522213
template.severity,
@@ -2258,18 +2219,11 @@ def add_template(request):
22582219
form.save_m2m()
22592220
# Ensure template tags exist in Finding's tag model
22602221
ensure_template_tags_in_finding_model(template)
2261-
count = apply_cwe_mitigation(
2262-
form.cleaned_data["apply_to_findings"], template,
2263-
)
2264-
if count > 0:
2265-
apply_message = (
2266-
" and " + str(count) + pluralize(count, "finding,findings") + " "
2267-
)
22682222

22692223
messages.add_message(
22702224
request,
22712225
messages.SUCCESS,
2272-
"Template created successfully. " + apply_message,
2226+
"Template created successfully.",
22732227
extra_tags="alert-success",
22742228
)
22752229
return HttpResponseRedirect(reverse("templates"))
@@ -2308,15 +2262,10 @@ def edit_template(request, tid):
23082262
# Ensure template tags exist in Finding's tag model
23092263
ensure_template_tags_in_finding_model(template)
23102264

2311-
count = apply_cwe_mitigation(
2312-
form.cleaned_data["apply_to_findings"], template,
2313-
)
2314-
apply_message = " and " + str(count) + " " + pluralize(count, "finding,findings") + " " if count > 0 else ""
2315-
23162265
messages.add_message(
23172266
request,
23182267
messages.SUCCESS,
2319-
"Template " + apply_message + "updated successfully.",
2268+
"Template updated successfully.",
23202269
extra_tags="alert-success",
23212270
)
23222271
return HttpResponseRedirect(reverse("templates"))
@@ -2327,14 +2276,12 @@ def edit_template(request, tid):
23272276
extra_tags="alert-danger",
23282277
)
23292278

2330-
count = apply_cwe_mitigation(apply_to_findings=True, template=template, update=False)
23312279
add_breadcrumb(title="Edit Template", top_level=False, request=request)
23322280
return render(
23332281
request,
23342282
"dojo/add_template.html",
23352283
{
23362284
"form": form,
2337-
"count": count,
23382285
"name": "Edit Template",
23392286
"template": template,
23402287
},

dojo/forms.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,6 @@ class Meta:
16561656

16571657

16581658
class FindingTemplateForm(forms.ModelForm):
1659-
apply_to_findings = forms.BooleanField(required=False, help_text="Apply template to all findings that match this CWE. (Update will overwrite mitigation, impact and references for any active, verified findings.)")
16601659
title = forms.CharField(max_length=1000, required=True)
16611660

16621661
cwe = forms.IntegerField(label="CWE", required=False)
@@ -1669,7 +1668,7 @@ class FindingTemplateForm(forms.ModelForm):
16691668
"required": "Select valid choice: In Progress, On Hold, Completed",
16701669
"invalid_choice": "Select valid choice: Critical,High,Medium,Low"})
16711670

1672-
field_order = ["title", "cwe", "vulnerability_ids", "severity", "cvssv3", "description", "mitigation", "impact", "references", "tags", "template_match", "template_match_cwe", "template_match_title", "apply_to_findings"]
1671+
field_order = ["title", "cwe", "vulnerability_ids", "severity", "cvssv3", "description", "mitigation", "impact", "references", "tags"]
16731672

16741673
def __init__(self, *args, **kwargs):
16751674
super().__init__(*args, **kwargs)

dojo/models.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -475,12 +475,6 @@ class System_Settings(models.Model):
475475
help_text=_("Enables Benchmarks such as the OWASP ASVS "
476476
"(Application Security Verification Standard)"))
477477

478-
enable_template_match = models.BooleanField(
479-
default=False,
480-
blank=False,
481-
verbose_name=_("Enable Remediation Advice"),
482-
help_text=_("Enables global remediation advice and matching on CWE and Title. The text will be replaced for mitigation, impact and references on a finding. Useful for providing consistent impact and remediation advice regardless of the scanner."))
483-
484478
enable_similar_findings = models.BooleanField(
485479
default=True,
486480
blank=False,
@@ -2814,10 +2808,6 @@ def save(self, dedupe_option=True, rules_option=True, product_grading_option=Tru
28142808
self.set_hash_code(dedupe_option)
28152809

28162810
if is_new_finding:
2817-
# We enter here during the first call from serializers.py
2818-
from dojo.utils import apply_cwe_to_template # noqa: PLC0415 circular import
2819-
# No need to use the returned variable since `self` Is updated in memory
2820-
apply_cwe_to_template(self)
28212811
if (self.file_path is not None) and (len(self.unsaved_endpoints) == 0):
28222812
self.static_finding = True
28232813
self.dynamic_finding = False
@@ -3661,8 +3651,6 @@ class Finding_Template(models.Model):
36613651
references = models.TextField(null=True, blank=True, db_column="refs")
36623652
last_used = models.DateTimeField(null=True, editable=False)
36633653
numerical_severity = models.CharField(max_length=4, null=True, blank=True, editable=False)
3664-
template_match = models.BooleanField(default=False, verbose_name=_("Template Match Enabled"), help_text=_("Enables this template for matching remediation advice. Match will be applied to all active, verified findings by CWE."))
3665-
template_match_title = models.BooleanField(default=False, verbose_name=_("Match Template by Title and CWE"), help_text=_("Matches by title text (contains search) and CWE."))
36663654

36673655
tags = TagField(blank=True, force_lowercase=True, help_text=_("Add tags that help describe this finding template. Choose from the list or add new tags. Press Enter key to add."))
36683656

dojo/templates/dojo/add_template.html

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@ <h3> {{ name }} {{ template }}</h3>
2222
<form id="add_template" class="form-horizontal" method="post">{% csrf_token %}
2323
{% include "dojo/form_fields.html" with form=form %}
2424
<div class="form-group">
25-
{% if count > 0 %}
26-
<div class="col-sm-offset-2 col-sm-10">
27-
<p>{{ count }} active, verified finding{{ count|pluralize }} match this template.</p>
28-
</div>
29-
{% endif %}
3025
<div class="col-sm-offset-2 col-sm-10">
3126
<button class="btn btn-primary" type="submit" name="add_template">Save Template</button>
3227
</div>

dojo/templates/dojo/templates.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ <h3 class="has-filters">
7676
</a>
7777
{% endif %}
7878
</td>
79-
<td>{{ finding.template_match }}</td>
8079
<td>
8180
{% if add_from_template %}
8281
<a href="{% url 'add_temp_finding' tid finding.id %}"

dojo/templates/dojo/view_finding.html

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -101,24 +101,7 @@ <h3 class="pull-left finding-title">
101101
</a>
102102
</li>
103103
{% endif %}
104-
{% if cwe_template.cwe and finding|has_object_permission:"Finding_Edit" %}
105-
<li role="presentation">
106-
<a class="apply-cwe-finding" href="#">
107-
<i class="fa-solid fa-copy"></i> Apply CWE Template Remediation to Finding
108-
</a>
109-
</li>
110-
<form id="apply-cwe-finding-form" method="post" action="{% url 'apply_template_cwe' finding.id %}">
111-
{% csrf_token %}
112-
<input type="hidden" label="apply_template" aria-label="apply_template" name="id" value="{{ finding.id }}"/>
113-
</form>
114-
{% endif %}
115-
{% if not cwe_template.cwe and "Finding_Add"|has_global_permission %}
116-
<li role="presentation">
117-
<a href="{% url 'add_template' %}">
118-
<i class="fa-solid fa-copy"></i> Create a CWE Remediation Template
119-
</a>
120-
</li>
121-
{% endif %}
104+
122105
{% if finding|has_object_permission:"Finding_Edit" %}
123106
<li role="presentation">
124107
<a href="{% url 'find_template_to_apply' finding.id %}">
@@ -1273,12 +1256,6 @@ <h4>Credential
12731256

12741257
});
12751258

1276-
$('a.apply-cwe-finding').on('click', function (e) {
1277-
if (confirm('Apply CWE template to this finding? (This will overwrite mitigation, impact and references.)')) {
1278-
$("form#apply-cwe-finding-form").submit();
1279-
}
1280-
1281-
});
12821259

12831260
$("a#next").on('click', function (e) {
12841261
e.preventDefault();

dojo/utils.py

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,27 +1427,6 @@ def add_language(product, language, files=1, code=1):
14271427
pass
14281428

14291429

1430-
# Apply finding template data by matching CWE + Title or CWE
1431-
def apply_cwe_to_template(finding, *, override=False):
1432-
if System_Settings.objects.get().enable_template_match or override:
1433-
# Attempt to match on CWE and Title First
1434-
template = Finding_Template.objects.filter(
1435-
cwe=finding.cwe, title__icontains=finding.title, template_match=True).first()
1436-
1437-
# If none then match on CWE
1438-
template = Finding_Template.objects.filter(
1439-
cwe=finding.cwe, template_match=True).first()
1440-
1441-
if template:
1442-
finding.mitigation = template.mitigation
1443-
finding.impact = template.impact
1444-
finding.references = template.references
1445-
template.last_used = timezone.now()
1446-
template.save()
1447-
1448-
return finding
1449-
1450-
14511430
def truncate_with_dots(the_string, max_length_including_dots):
14521431
if not the_string:
14531432
return the_string

0 commit comments

Comments
 (0)