Skip to content

Commit 5ee3dc4

Browse files
devGregAclaude
andcommitted
Decorator and permissions updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 70c3889 commit 5ee3dc4

8 files changed

Lines changed: 533 additions & 8 deletions

File tree

dojo/api_v2/views.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,8 @@ def download_file(self, request, file_id, pk=None):
700700
responses={status.HTTP_200_OK: serializers.EngagementUpdateJiraEpicSerializer},
701701
)
702702
@action(
703-
detail=True, methods=["post"], permission_classes=[IsAuthenticated],
703+
detail=True, methods=["post"],
704+
permission_classes=(IsAuthenticated, permissions.UserHasEngagementRelatedObjectPermission),
704705
)
705706
def update_jira_epic(self, request, pk=None):
706707
engagement = self.get_object()

dojo/engagement/views.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,9 @@ def edit_risk_acceptance(request, eid, raid):
13781378
def view_edit_risk_acceptance(request, eid, raid, *, edit_mode=False):
13791379
risk_acceptance = get_object_or_404(Risk_Acceptance, pk=raid)
13801380
eng = get_object_or_404(Engagement, pk=eid)
1381+
# Ensure the risk acceptance belongs to the supplied engagement
1382+
if not Engagement.objects.filter(risk_acceptance=risk_acceptance, id=eid).exists():
1383+
raise PermissionDenied
13811384

13821385
if edit_mode and not eng.product.enable_full_risk_acceptance:
13831386
raise PermissionDenied
@@ -1539,6 +1542,9 @@ def expire_risk_acceptance(request, eid, raid):
15391542
risk_acceptance = get_object_or_404(prefetch_for_expiration(Risk_Acceptance.objects.all()), pk=raid)
15401543
# Validate the engagement ID exists before moving forward
15411544
get_object_or_404(Engagement, pk=eid)
1545+
# Ensure the risk acceptance belongs to the supplied engagement
1546+
if not Engagement.objects.filter(risk_acceptance=risk_acceptance, id=eid).exists():
1547+
raise PermissionDenied
15421548

15431549
ra_helper.expire_now(risk_acceptance)
15441550

@@ -1549,6 +1555,9 @@ def expire_risk_acceptance(request, eid, raid):
15491555
def reinstate_risk_acceptance(request, eid, raid):
15501556
risk_acceptance = get_object_or_404(prefetch_for_expiration(Risk_Acceptance.objects.all()), pk=raid)
15511557
eng = get_object_or_404(Engagement, pk=eid)
1558+
# Ensure the risk acceptance belongs to the supplied engagement
1559+
if not Engagement.objects.filter(risk_acceptance=risk_acceptance, id=eid).exists():
1560+
raise PermissionDenied
15521561

15531562
if not eng.product.enable_full_risk_acceptance:
15541563
raise PermissionDenied
@@ -1562,6 +1571,9 @@ def reinstate_risk_acceptance(request, eid, raid):
15621571
def delete_risk_acceptance(request, eid, raid):
15631572
risk_acceptance = get_object_or_404(Risk_Acceptance, pk=raid)
15641573
eng = get_object_or_404(Engagement, pk=eid)
1574+
# Ensure the risk acceptance belongs to the supplied engagement
1575+
if not Engagement.objects.filter(risk_acceptance=risk_acceptance, id=eid).exists():
1576+
raise PermissionDenied
15651577

15661578
ra_helper.delete(eng, risk_acceptance)
15671579

dojo/finding/views.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import dojo.finding.helper as finding_helper
3333
import dojo.jira_link.helper as jira_helper
3434
import dojo.risk_acceptance.helper as ra_helper
35-
from dojo.authorization.authorization import user_has_permission_or_403
35+
from dojo.authorization.authorization import user_has_global_permission_or_403, user_has_permission_or_403
3636
from dojo.authorization.authorization_decorators import (
3737
user_has_global_permission,
3838
user_is_authorized,
@@ -1732,6 +1732,9 @@ def mktemplate(request, fid):
17321732

17331733
@user_is_authorized(Finding, Permissions.Finding_Edit, "fid")
17341734
def find_template_to_apply(request, fid):
1735+
# Templates may contain sensitive data from any product; require global permission
1736+
# to match the authorization level of the /template list view
1737+
user_has_global_permission_or_403(request.user, Permissions.Finding_Edit)
17351738
finding = get_object_or_404(Finding, id=fid)
17361739
test = get_object_or_404(Test, id=finding.test.id)
17371740
templates_by_cve = (

dojo/product/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,7 +1597,7 @@ def engagement_presets(request, pid):
15971597
@user_is_authorized(Product, Permissions.Product_Edit, "pid")
15981598
def edit_engagement_presets(request, pid, eid):
15991599
prod = get_object_or_404(Product, id=pid)
1600-
preset = get_object_or_404(Engagement_Presets, id=eid)
1600+
preset = get_object_or_404(Engagement_Presets, id=eid, product_id=pid)
16011601

16021602
product_tab = Product_Tab(prod, title=_("Edit Engagement Preset"), tab="settings")
16031603

@@ -1646,7 +1646,7 @@ def add_engagement_presets(request, pid):
16461646
@user_is_authorized(Product, Permissions.Product_Edit, "pid")
16471647
def delete_engagement_presets(request, pid, eid):
16481648
prod = get_object_or_404(Product, id=pid)
1649-
preset = get_object_or_404(Engagement_Presets, id=eid)
1649+
preset = get_object_or_404(Engagement_Presets, id=eid, product_id=pid)
16501650
form = DeleteEngagementPresetsForm(instance=preset)
16511651

16521652
if request.method == "POST":

dojo/survey/views.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
@user_is_authorized(Engagement, Permissions.Engagement_Edit, "eid")
5858
def delete_engagement_survey(request, eid, sid):
5959
engagement = get_object_or_404(Engagement, id=eid)
60-
survey = get_object_or_404(Answered_Survey, id=sid)
60+
survey = get_object_or_404(Answered_Survey, id=sid, engagement_id=eid)
6161
questions = get_answered_questions(survey=survey, read_only=True)
6262
form = Delete_Questionnaire_Form(instance=survey)
6363

@@ -96,7 +96,7 @@ def delete_engagement_survey(request, eid, sid):
9696

9797

9898
def answer_questionnaire(request, eid, sid):
99-
survey = get_object_or_404(Answered_Survey, id=sid)
99+
survey = get_object_or_404(Answered_Survey, id=sid, engagement_id=eid)
100100
engagement = get_object_or_404(Engagement, id=eid)
101101
system_settings = System_Settings.objects.all()[0]
102102

@@ -162,7 +162,7 @@ def answer_questionnaire(request, eid, sid):
162162

163163
@user_is_authorized(Engagement, Permissions.Engagement_Edit, "eid")
164164
def assign_questionnaire(request, eid, sid):
165-
survey = get_object_or_404(Answered_Survey, id=sid)
165+
survey = get_object_or_404(Answered_Survey, id=sid, engagement_id=eid)
166166
engagement = get_object_or_404(Engagement, id=eid)
167167

168168
form = AssignUserForm(instance=survey)
@@ -183,7 +183,7 @@ def assign_questionnaire(request, eid, sid):
183183

184184
@user_is_authorized(Engagement, Permissions.Engagement_View, "eid")
185185
def view_questionnaire(request, eid, sid):
186-
survey = get_object_or_404(Answered_Survey, id=sid)
186+
survey = get_object_or_404(Answered_Survey, id=sid, engagement_id=eid)
187187
engagement = get_object_or_404(Engagement, id=eid)
188188
questions = get_answered_questions(survey=survey, read_only=True)
189189

dojo/tools/ms_defender/parser.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ def get_findings(self, file, test):
4242
else:
4343
input_zip = zipfile.ZipFile(file, "r")
4444

45+
max_size = 256 * 1024 * 1024 # 256 MB
46+
total_size = sum(info.file_size for info in input_zip.infolist())
47+
if total_size > max_size:
48+
msg = f"Zip file uncompressed content exceeds maximum allowed size ({total_size} > {max_size})"
49+
raise ValueError(msg)
4550
zipdata = {name: input_zip.read(name) for name in input_zip.namelist()}
4651
vulnerabilityfiles = []
4752
machinefiles = []

dojo/tools/sonarqube/parser.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ def get_findings(self, file, test):
4242
input_zip = zipfile.ZipFile(file.name, "r")
4343
else:
4444
input_zip = zipfile.ZipFile(file, "r")
45+
max_size = 256 * 1024 * 1024 # 256 MB
46+
total_size = sum(info.file_size for info in input_zip.infolist())
47+
if total_size > max_size:
48+
msg = f"Zip file uncompressed content exceeds maximum allowed size ({total_size} > {max_size})"
49+
raise ValueError(msg)
4550
zipdata = {name: input_zip.read(name) for name in input_zip.namelist()}
4651
return SonarQubeRESTAPIZIP().get_items(zipdata, test, self.mode)
4752
parser = etree.HTMLParser()

0 commit comments

Comments
 (0)