Skip to content

Conversation

@Siryu6
Copy link

@Siryu6 Siryu6 commented Oct 29, 2025

Description

This PR implements a dry_run feature for reimport-scan operations that allows users to preview what changes would occur during a reimport without making any database modifications.

Key Features:

  • Optional dry_run boolean parameter (defaults to false) on reimport-scan API endpoints
  • Returns detailed statistics about findings that would be created, reactivated, closed, or left untouched
  • Respects all existing reimport parameters (close_old_findings, do_not_reactivate, severity filters, etc.)
  • Non-breaking: all existing functionality remains unchanged

Use Case:
This feature is particularly useful for CI/CD pipelines where teams want to validate scan results and preview changes before merging to production environments.

API Response Example:

{
  "test_id": 123,
  "dry_run": true,
  "changes_preview": {
    "would_create": 5,
    "would_reactivate": 2,
    "would_close": 3,
    "would_leave_untouched": 10,
    "total_changes": 10
  },
  "findings_details": {
    "new_findings": [...],
    "reactivated_findings": [...],
    "closed_findings": [...],
    "unchanged_findings": [...]
  }
}

Documentation

API documentation is included in the serializer field descriptions (help_text).

Files Changed

  • dojo/api_v2/serializers.py - API integration for dry_run parameter
  • dojo/importers/default_reimporter.py - Core dry_run_reimport() logic
  • dojo/importers/default_importer.py - Return signature update
  • dojo/importers/options.py - dry_run parameter validation
  • dojo/fixtures/dojo_testdata.json - Fixed missing SLA_Configuration
  • dojo/engagement/views.py - View layer dry_run support
  • dojo/test/views.py - View layer dry_run support
  • unittests/dojo_test_case.py - Test helper methods
  • unittests/test_import_reimport.py - Minor test adjustments
  • unittests/test_import_reimport_dry_run.py - New comprehensive test suite

Labels to add:

  • enhancement
  • feature

Implements optional dry_run parameter for reimport-scan API endpoints
to preview changes without modifying the database. Useful for CI/CD
pipelines to validate scan results before merging to production.

- Add dry_run parameter to reimport-scan API endpoints
- Implement dry_run_reimport() method respecting all reimport options
- Return detailed preview statistics and findings details
- Add comprehensive test suite with 10 test cases
- Fix missing SLA_Configuration in test fixtures
@dryrunsecurity
Copy link

DryRun Security

🔴 Risk threshold exceeded.

This pull request modifies several sensitive codepaths (serializers, engagement views, importers, test views) and contains security issues: missing authorization on reopen_eng (IDOR), unsafe removal of findings in view_edit_risk_acceptance (IDOR), and possible information disclosure by prefetching finding/group details into templates. These changes should be reviewed to add proper access checks and restrict edits to listed sensitive files/authors.

🔴 Configured Codepaths Edit in dojo/api_v2/serializers.py
Vulnerability Configured Codepaths Edit
Description Sensitive edits detected for this file. Sensitive file paths and allowed authors can be configured in .dryrunsecurity.yaml.
🔴 Configured Codepaths Edit in dojo/engagement/views.py
Vulnerability Configured Codepaths Edit
Description Sensitive edits detected for this file. Sensitive file paths and allowed authors can be configured in .dryrunsecurity.yaml.
🔴 Configured Codepaths Edit in dojo/importers/default_importer.py
Vulnerability Configured Codepaths Edit
Description Sensitive edits detected for this file. Sensitive file paths and allowed authors can be configured in .dryrunsecurity.yaml.
🔴 Configured Codepaths Edit in dojo/importers/default_reimporter.py
Vulnerability Configured Codepaths Edit
Description Sensitive edits detected for this file. Sensitive file paths and allowed authors can be configured in .dryrunsecurity.yaml.
🔴 Configured Codepaths Edit in dojo/importers/options.py
Vulnerability Configured Codepaths Edit
Description Sensitive edits detected for this file. Sensitive file paths and allowed authors can be configured in .dryrunsecurity.yaml.
🔴 Configured Codepaths Edit in dojo/test/views.py
Vulnerability Configured Codepaths Edit
Description Sensitive edits detected for this file. Sensitive file paths and allowed authors can be configured in .dryrunsecurity.yaml.
🟡 Potential IDOR Vulnerability in dojo/engagement/views.py
Vulnerability Potential IDOR Vulnerability
Description The reopen_eng function retrieves an Engagement object using a user-supplied ID (eid) without any explicit authorization checks. While the edit_engagement and delete_engagement functions in the same file are protected by @user_is_authorized(Engagement, Permissions.Engagement_Edit, "eid"), the reopen_eng function lacks this or any similar decorator. This allows any authenticated user to potentially reopen any engagement by manipulating the eid parameter in the URL, leading to an Insecure Direct Object Reference (IDOR) vulnerability. The reopen_engagement function itself does not perform authorization checks, relying on the caller to enforce permissions.

eng = Engagement.objects.get(id=eid)
reopen_engagement(eng)
messages.add_message(request, messages.SUCCESS, "Engagement reopened successfully.", extra_tags="alert-success")
return HttpResponseRedirect(reverse("view_engagements", args=(eng.product.id,)))

Information Disclosure via Finding Group Details Exposure in dojo/test/views.py
Vulnerability Information Disclosure via Finding Group Details Exposure
Description The get_initial_context method adds finding_groups to the template context, prefetching related findings, jira_issue, creator, and findings__vulnerability_id_set. This loads potentially sensitive data into memory and passes it to the template. Without explicit, fine-grained authorization checks applied to each prefetched related object before rendering, a user with access to the test view could potentially view details of findings, Jira issues, or vulnerability IDs that they are not otherwise authorized to see.

"person": request.user.username,
"request": request,
"show_re_upload": any(test.test_type.name in code for code in get_choices_sorted()),
"creds": Cred_Mapping.objects.filter(engagement=test.engagement)
.select_related("cred_id")
.order_by("cred_id"),
"cred_test": Cred_Mapping.objects.filter(test=test).select_related("cred_id").order_by("cred_id"),
"jira_project": jira_helper.get_jira_project(test),
"bulk_edit_form": FindingBulkUpdateForm(request.GET),
"enable_table_filtering": get_system_setting("enable_ui_table_based_searching"),
"finding_groups": test.finding_group_set.all().prefetch_related(
"findings", "jira_issue", "creator", "findings__vulnerability_id_set"
),
"finding_group_by_options": Finding_Group.GROUP_BY_OPTIONS,
}
# Set the form using the context, and then update the context

Insecure Direct Object Reference (IDOR) in dojo/engagement/views.py
Vulnerability Insecure Direct Object Reference (IDOR)
Description The view_edit_risk_acceptance function in dojo/engagement/views.py allows a user to remove a finding from a risk acceptance. When processing the 'remove_finding' action, the function retrieves the Finding object using get_object_or_404(Finding, pk=request.POST["remove_finding_id"]). The pk (primary key) is taken directly from user input without any validation to ensure that the requested finding belongs to the engagement (eid) that the user is authorized to access. This means an attacker could potentially manipulate the remove_finding_id parameter to remove a finding from a risk acceptance in an engagement they are not authorized for, leading to an Insecure Direct Object Reference (IDOR).

@cache_page(60 * 5) # cache for 5 minutes
@vary_on_cookie
def engagement_calendar(request):
if not get_system_setting("enable_calendar"):
raise Resolver404

We've notified @mtesauro.


All finding details can be found in the DryRun Security Dashboard.

Copy link
Member

@valentijnscholten valentijnscholten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR. We'll take a look and see if the feature is something that we can add without adding too much maintenance burden. Although we have lifted the feature freeze, it's still advised to double check before starting a PR.

Some initial thoughts:

  • More than half of the changes in the PR seem to be cosmetic. Would it be possible to revert these cosmetic changes so it becomes easier to digest and review?
  • The dry_run now seems to be a code path seperate from the "real" reimport. Have you considered using the rel reimport code path and add some if-statements to make a dry_run mode? Two code paths increase the risk of differences/mismatches.
  • The reimport matching logic can be influenced by finding that are created during reimport. For example if finding 100 and 101 in the report are new and both have the same hash_code, the finding 101 will not be imported as it is matched against finding 100. In dry_run mode this match won't happen, so the statistics might be different. I haven't verified this, but this is what I am thinking.
  • The reimport process might change in the near future where it will perform batch based matching and/or batch processing of the report. I am not sure if it will be possible to maintain a 100% complete dry_run feature.

@Siryu6
Copy link
Author

Siryu6 commented Oct 30, 2025

More than half of the changes in the PR seem to be cosmetic. Would it be possible to revert these cosmetic changes so it becomes easier to digest and review?

Yeah my bad, that's my IDE 😅 I'll revert that.

The dry_run now seems to be a code path seperate from the "real" reimport. Have you considered using the rel reimport code path and add some if-statements to make a dry_run mode? Two code paths increase the risk of differences/mismatches.

I first did that but it was lot of if conditions, didn't like it and decided to separate it, if you prefer this i can switch to that.

The reimport matching logic can be influenced by finding that are created during reimport. For example if finding 100 and 101 in the report are new and both have the same hash_code, the finding 101 will not be imported as it is matched against finding 100. In dry_run mode this match won't happen, so the statistics might be different. I haven't verified this, but this is what I am thinking.

I'll verify its properly implemented and fix it if it's not the case.

The reimport process might change in the near future where it will perform batch based matching and/or batch processing of the report. I am not sure if it will be possible to maintain a 100% complete dry_run feature.

I guess that's a good reason to switch to if statements 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants