Skip to content

Release: Merge release into master from: release/2.50.4#13275

Merged
rossops merged 16 commits intomasterfrom
release/2.50.4
Sep 29, 2025
Merged

Release: Merge release into master from: release/2.50.4#13275
rossops merged 16 commits intomasterfrom
release/2.50.4

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Release triggered by rossops

DefectDojo release bot and others added 16 commits September 22, 2025 16:01
….51.0-dev

Release: Merge back 2.50.2 into bugfix from: master-into-bugfix/2.50.2-2.51.0-dev
* sonarqube hotspots sync implementation

* params fix

* ruff fixes

* ruff fixes
…uplicates in edit forms" and bump django-multiselectfield from 0.1.13 to 1.0.1 (#13250)

This reverts commits 008cdff and 887d426.
Also cherryicks b5ef554 from #12601
Add an Engagement's branch_tag in Jira Epic's description
[docs] update changelog 2.50.3
Added Line Field for SonarQube Scan and SonarQube Scan Detailed Scan Types
@dryrunsecurity
Copy link
Copy Markdown

dryrunsecurity Bot commented Sep 29, 2025

DryRun Security

🔴 Risk threshold exceeded.

This pull request modifies multiple sensitive files (dojo/jira_link/helper.py, dojo/forms.py, dojo/utils.py) triggering configured codepath alerts, introduces a potential stored XSS by inserting unsanitized engagement.name and engagement.branch_tag into Jira issue descriptions (dojo/jira_link/helper.py, lines ~1401–1416), and contains complex SonarQube update logic that may produce incorrect or incomplete transition sequences for hotspots (dojo/tools/api_sonarqube/updater.py, lines ~185–240).

🔴 Configured Codepaths Edit in dojo/jira_link/helper.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/jira_link/helper.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/forms.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/utils.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/jira_link/helper.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/forms.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 Cross-Site Scripting in dojo/jira_link/helper.py
Vulnerability Potential Cross-Site Scripting
Description The patch assigns user-controllable values (engagement.name and engagement.branch_tag) into the Jira issue "description" field without any escaping or sanitization and then submits them to the Jira API. If either engagement.name or engagement.branch_tag can contain attacker-controlled input (for example, via fields a user can set), that input could include HTML or JavaScript payloads. When Jira renders the issue description in its web UI, those payloads may be interpreted as HTML/JS, leading to stored (persistent) XSS. The code paths of concern are the new concatenation into description and passing that description directly in jira_issue_update_kwargs, which sends the value to the server-side rendering context in Jira.

jira = get_jira_connection(jira_instance)
j_issue = get_jira_issue(engagement)
issue = jira.issue(j_issue.jira_id)
epic_name = kwargs.get("epic_name")
if not epic_name:
epic_name = engagement.name
description = epic_name
branch_tag = engagement.branch_tag
if branch_tag:
description += "\nBranch: " + branch_tag
jira_issue_update_kwargs = {
"summary": epic_name,
"description": description,
}
if (epic_priority := kwargs.get("epic_priority")) is not None:
jira_issue_update_kwargs["priority"] = {"name": epic_priority}

Potential for Inconsistent State due to Complex Logic in dojo/tools/api_sonarqube/updater.py
Vulnerability Potential for Inconsistent State due to Complex Logic
Description The logic for updating SonarQube issues and hotspots is complex, involving separate state machines and transition mappings. While the code attempts to differentiate between regular issues and hotspots, the get_sonarqube_required_transitions_for function, particularly the else block for hotspots, does not fully implement a robust transition logic. It only considers the first transition in the transitions list, which might not be sufficient for multi-step transitions or when multiple paths exist to a target state. This could lead to situations where DefectDojo attempts to apply an incorrect or incomplete transition sequence, resulting in an inconsistent state between DefectDojo and SonarQube for hotspots.

# during import
target_status = self.get_sonarqube_status_for(finding)
is_hotspot = sonarqube_issue.type == "SECURITY_HOTSPOT"
issue = client.get_hotspot(sonarqube_issue.key) if is_hotspot else client.get_issue(sonarqube_issue.key)
# Issue does not exist (could have disappeared in SQ because a previous scan resolved it)
if not issue:
return
if is_hotspot:
current_status = issue.get("status")
elif issue.get("resolution"):
current_status = "{} / {}".format(issue.get("status"), issue.get("resolution"))
else:
current_status = issue.get("status")
# Get required transitions
transitions = self.get_sonarqube_required_transitions_for(
current_status, target_status, is_hotspot=is_hotspot,
)
if not transitions:
logger.debug(
f"There are no transitions between {current_status} and {target_status} for finding '{finding}' in SonarQube",
)
return
logger.debug(
f"Updating finding '{finding}' transition {current_status} -> {target_status} in SonarQube",
)
# Apply transitions
for transition in transitions:
if is_hotspot:
client.transition_hotspot(sonarqube_issue.key,
status=transition["status"],
resolution=transition["resolution"])
else:
client.transition_issue(sonarqube_issue.key, transition)
# Track that Defect Dojo has updated the SonarQube issue
Sonarqube_Issue_Transition.objects.create(
sonarqube_issue=finding.sonarqube_issue,
# not sure if this is needed, but looks like the original author decided to send display status
# to sonarqube we changed Accepted into Risk Accepted, but we change it back to be sure we don't
# break the integration
finding_status=finding.status().replace(
"Risk Accepted", "Accepted",
)
if finding.status()
else finding.status(),
sonarqube_status=current_status,
transitions=",".join(transition["status"] if is_hotspot else transition for transition in transitions),
)

We've notified @mtesauro.


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

@rossops rossops merged commit 4527392 into master Sep 29, 2025
83 checks passed
Maffooch pushed a commit to valentijnscholten/django-DefectDojo that referenced this pull request Feb 16, 2026
Release: Merge release into master from: release/2.50.4
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.

6 participants