Skip to content

Commit 70c2c19

Browse files
Maffoochclaude
andcommitted
Fix information disclosure in conflict validation error messages
Replace error messages that leaked resolved object names (product names, engagement names) with generic messages. An attacker could enumerate object names by sending conflicting ID-based and name-based identifiers and reading the detailed error responses. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4c20712 commit 70c2c19

File tree

2 files changed

+9
-9
lines changed

2 files changed

+9
-9
lines changed

dojo/api_v2/permissions.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,10 +475,10 @@ def has_permission(self, request, view):
475475
if engagement := converted_dict.get("engagement"):
476476
# Validate the resolved engagement's parent chain matches any provided identifiers
477477
if (product := converted_dict.get("product")) and engagement.product_id != product.id:
478-
msg = f'The resolved engagement is associated with product "{engagement.product.name}", not with product "{converted_dict.get("product_name")}"'
478+
msg = "The provided identifiers are inconsistent — the engagement does not belong to the specified product."
479479
raise ValidationError(msg)
480480
if (engagement_name := converted_dict.get("engagement_name")) and engagement.name != engagement_name:
481-
msg = f'The resolved engagement is named "{engagement.name}", not "{engagement_name}"'
481+
msg = "The provided identifiers are inconsistent — the engagement name does not match the specified engagement."
482482
raise ValidationError(msg)
483483
return user_has_permission(
484484
request.user, engagement, Permissions.Import_Scan_Result,
@@ -787,17 +787,17 @@ def has_permission(self, request, view):
787787
if test := converted_dict.get("test"):
788788
# Validate the resolved test's parent chain matches any provided identifiers
789789
if (product := converted_dict.get("product")) and test.engagement.product_id != product.id:
790-
msg = f'The resolved test is associated with product "{test.engagement.product.name}", not with product "{converted_dict.get("product_name")}"'
790+
msg = "The provided identifiers are inconsistent — the test does not belong to the specified product."
791791
raise ValidationError(msg)
792792
if (engagement := converted_dict.get("engagement")) and test.engagement_id != engagement.id:
793-
msg = f'The resolved test is associated with engagement "{test.engagement.name}", not with engagement "{converted_dict.get("engagement_name")}"'
793+
msg = "The provided identifiers are inconsistent — the test does not belong to the specified engagement."
794794
raise ValidationError(msg)
795795
# Also validate by name when the objects were not resolved (e.g. names that match no existing record)
796796
if not converted_dict.get("product") and (product_name := converted_dict.get("product_name")) and test.engagement.product.name != product_name:
797-
msg = f'The resolved test is associated with product "{test.engagement.product.name}", not with product "{product_name}"'
797+
msg = "The provided identifiers are inconsistent — the test does not belong to the specified product."
798798
raise ValidationError(msg)
799799
if not converted_dict.get("engagement") and (engagement_name := converted_dict.get("engagement_name")) and test.engagement.name != engagement_name:
800-
msg = f'The resolved test is associated with engagement "{test.engagement.name}", not with engagement "{engagement_name}"'
800+
msg = "The provided identifiers are inconsistent — the test does not belong to the specified engagement."
801801
raise ValidationError(msg)
802802
return user_has_permission(
803803
request.user, test, Permissions.Import_Scan_Result,
@@ -1207,7 +1207,7 @@ def check_auto_create_permission(
12071207
if engagement:
12081208
# Validate the resolved engagement's parent chain matches any provided names
12091209
if product is not None and engagement.product_id != product.id:
1210-
msg = f'The resolved engagement is associated with product "{engagement.product.name}", not with product "{product_name}"'
1210+
msg = "The provided identifiers are inconsistent — the engagement does not belong to the specified product."
12111211
raise ValidationError(msg)
12121212
return user_has_permission(
12131213
user, engagement, Permissions.Import_Scan_Result,

dojo/importers/auto_create_context.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def get_target_engagement_if_exists(
182182
if engagement := get_object_or_none(Engagement, pk=engagement_id):
183183
logger.debug("Using existing engagement by id: %s", engagement_id)
184184
if product is not None and engagement.product_id != product.id:
185-
msg = f'Engagement "{engagement_id}" does not belong to product "{product}"'
185+
msg = "The provided identifiers are inconsistent — the engagement does not belong to the specified product."
186186
raise ValueError(msg)
187187
return engagement
188188
# if there's no product, then for sure there's no engagement either
@@ -207,7 +207,7 @@ def get_target_test_if_exists(
207207
if test := get_object_or_none(Test, pk=test_id):
208208
logger.debug("Using existing Test by id: %s", test_id)
209209
if engagement is not None and test.engagement_id != engagement.id:
210-
msg = f'Test "{test_id}" does not belong to engagement "{engagement}"'
210+
msg = "The provided identifiers are inconsistent — the test does not belong to the specified engagement."
211211
raise ValueError(msg)
212212
return test
213213
# If the engagement is not supplied, we cannot do anything

0 commit comments

Comments
 (0)