Skip to content

Release: Merge release into master from: release/2.48.3 #12829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 21, 2025
Merged

Conversation

github-actions[bot]
Copy link
Contributor

Release triggered by Maffooch

Copy link

dryrunsecurity bot commented Jul 21, 2025

DryRun Security

This pull request identifies several security and performance concerns, including a potential performance degradation risk in database querying, an inaccurate severity mapping vulnerability in the Trivy parser, and information disclosure risks through debug logging in multiple parsers that could expose sensitive vulnerability details if debug logging is enabled in a production environment.

Potential for Performance Degradation / DoS in dojo/models.py
Vulnerability Potential for Performance Degradation / DoS
Description The open_findings_list method, called by the APIv2 serializer, performs an unbounded database query to fetch all active finding IDs for a product. If a product has a very large number of findings, this operation can consume significant database and application resources, potentially leading to performance degradation or a Denial of Service.

def get_product_type(self):
return self.prod_type if self.prod_type is not None else "unknown"
# only used in APIv2 serializers.py, should be deprecated or at least prefetched
def open_findings_list(self):
findings = Finding.objects.filter(test__engagement__product=self, active=True).values_list("id", flat=True)
return list(findings)
@property
def has_jira_configured(self):

Potential for Inaccurate Severity Mapping in dojo/tools/trivy/parser.py
Vulnerability Potential for Inaccurate Severity Mapping
Description The Trivy parser in dojo/tools/trivy/parser.py processes CVSS scores by first checking the SeveritySource field from the input report. If this field is present, its value is prioritized over a hardcoded list of trusted CVSS sources (nvd, ghsa, redhat, bitnami). The code iterates through [detected_severity_source, *CVSS_SEVERITY_SOURCES] and uses the first matching CVSS data it finds, then breaks the loop. This means if an attacker can control the Trivy report content, they could set SeveritySource to point to a CVSS entry within the report that has a lower score, even if other, more severe, CVSS entries exist for the same vulnerability from trusted sources like NVD. This could lead to a high-severity vulnerability being incorrectly classified with a lower severity in DefectDojo, potentially causing it to be overlooked or deprioritized.

try:
vuln_id = vuln.get("VulnerabilityID", "0")
package_name = vuln["PkgName"]
detected_severity_source = vuln.get("SeveritySource", None)
cvss = vuln.get("CVSS", {})
cvssclass = None
cvssv3 = None
cvssv3_score = None
# Iterate over the possible severity sources tom find the first match
for severity_source in [detected_severity_source, *CVSS_SEVERITY_SOURCES]:
cvssclass = cvss.get(severity_source, None)
if cvssclass is not None:
break
# Parse the CVSS class if it is not None
if cvssclass is not None:
if cvss_data := parse_cvss_data(cvssclass.get("V3Vector", "")):
cvssv3 = cvss_data.get("vector")
cvssv3_score = cvss_data.get("score")
severity = cvss_data.get("severity")
elif (cvss_v3_score := cvssclass.get("V3Score")) is not None:
cvssv3_score = cvss_v3_score
severity = self.convert_cvss_score(cvss_v3_score)
elif (cvss_v2_score := cvssclass.get("V2Score")) is not None:
severity = self.convert_cvss_score(cvss_v2_score)
else:
severity = self.convert_cvss_score(None)
else:
severity = TRIVY_SEVERITIES[vuln["Severity"]]
if target_class == "os-pkgs" or target_class == "lang-pkgs":

Information Disclosure via Debug Logging in dojo/tools/anchore_grype/parser.py
Vulnerability Information Disclosure via Debug Logging
Description The code adds a logger.debug(f"data: {data}") statement in the Anchore Grype parser. The data variable contains the full parsed JSON content of an Anchore Grype report, which includes sensitive vulnerability details such as CVEs, GHSA IDs, descriptions, CVSS scores, and EPSS scores. If debug logging is enabled in a production environment (e.g., by setting DD_LOG_LEVEL=DEBUG), this sensitive information would be written to the application logs. If these logs are not adequately secured, it could lead to an information disclosure vulnerability, allowing unauthorized access to detailed vulnerability intelligence about the system.

)
def get_findings(self, file, test):
logger.debug(f"file: {file}")
data = json.load(file)
logger.debug(f"data: {data}")
dupes = {}
for item in data.get("matches", []):
vulnerability = item["vulnerability"]

Information Disclosure via Debug Logging in dojo/tools/dependency_check/parser.py
Vulnerability Information Disclosure via Debug Logging
Description The code logs the full exception object at the debug level (logger.debug(e)). If the DD_DEBUG environment variable is set to True in a production environment, this debug log level will be active, potentially leading to the disclosure of sensitive information such as stack traces, internal file paths, and snippets of processed data (e.g., malformed CVSS strings from vulnerability reports) in the application logs. This information could aid an attacker in understanding the application's internal structure and data handling.

return None, None
def get_severity_and_cvss_meta(self, vulnerability, namespace) -> dict:
# Get the base severity from the report
severity = vulnerability.findtext(f"{namespace}severity")
cvssv3 = None
cvssv3_score = None
# Attempt to add the CVSSv3 score, and update the severity accordingly
if (cvssv3_node := vulnerability.find(namespace + "cvssV3")) is not None:
try:
vector_parts = [
f"AV:{self.CVSS_V3_MAPPINGS['attackVector'][cvssv3_node.findtext(f'{namespace}attackVector')]}",
f"AC:{self.CVSS_V3_MAPPINGS['attackComplexity'][cvssv3_node.findtext(f'{namespace}attackComplexity')]}",
f"PR:{self.CVSS_V3_MAPPINGS['privilegesRequired'][cvssv3_node.findtext(f'{namespace}privilegesRequired')]}",
f"UI:{self.CVSS_V3_MAPPINGS['userInteraction'][cvssv3_node.findtext(f'{namespace}userInteraction')]}",
f"S:{self.CVSS_V3_MAPPINGS['scope'][cvssv3_node.findtext(f'{namespace}scope')]}",
f"C:{self.CVSS_V3_MAPPINGS['confidentialityImpact'][cvssv3_node.findtext(f'{namespace}confidentialityImpact')]}",
f"I:{self.CVSS_V3_MAPPINGS['integrityImpact'][cvssv3_node.findtext(f'{namespace}integrityImpact')]}",
f"A:{self.CVSS_V3_MAPPINGS['availabilityImpact'][cvssv3_node.findtext(f'{namespace}availabilityImpact')]}",
]
version = cvssv3_node.findtext("version") or "3.1"
vector = f"CVSS:{version}/" + "/".join(vector_parts)
if cvss_data := parse_cvss_data(vector):
cvssv3 = cvss_data.get("vector")
cvssv3_score = cvss_data.get("score")
severity = cvss_data.get("severity")
except Exception as e:
# Only log the error - there is not much we can do to recover from this
logger.debug(e)
elif (cvssv2_node := vulnerability.find(namespace + "cvssV2")) is not None:
severity = cvssv2_node.findtext(f"{namespace}severity").lower().capitalize()
# handle if the severity have something not in the mapping
# default to 'Medium' and produce warnings in logs
if severity:
if severity.strip().lower() not in self.SEVERITY_MAPPING:
logger.warning(
f"Warning: Unknow severity value detected '{severity}'. Bypass to 'Medium' value",
)
severity = "Medium"
else:
severity = self.SEVERITY_MAPPING[severity.strip().lower()]
else:
severity = "Medium"
return {
"severity": severity,
"cvssv3": cvssv3,
"cvssv3_score": cvssv3_score,
}
def get_finding_from_vulnerability(
self, dependency, related_dependency, vulnerability, test, namespace,
):


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

@Maffooch Maffooch merged commit ca80b76 into master Jul 21, 2025
84 checks passed
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.

3 participants