Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions dojo/tools/trivy/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ def get_result_items(self, test, results, service_name=None, artifact_name=""):
service=service_name,
**status_fields,
)
finding.unsaved_tags = [vul_type, target_class]
finding.unsaved_tags = [tag for tag in (vul_type, target_class) if tag]

if vuln_id:
finding.unsaved_vulnerability_ids = [vuln_id]
Expand Down Expand Up @@ -405,7 +405,7 @@ def get_result_items(self, test, results, service_name=None, artifact_name=""):
if misc_avdid:
finding.unsaved_vulnerability_ids = []
finding.unsaved_vulnerability_ids.append(misc_avdid)
finding.unsaved_tags = [target_type, target_class]
finding.unsaved_tags = [tag for tag in (target_type, target_class) if tag]
items.append(finding)

secrets = target_data.get("Secrets", [])
Expand Down Expand Up @@ -436,7 +436,7 @@ def get_result_items(self, test, results, service_name=None, artifact_name=""):
fix_available=True,
service=service_name,
)
finding.unsaved_tags = [target_class]
finding.unsaved_tags = [tag for tag in (target_class,) if tag]
items.append(finding)

licenses = target_data.get("Licenses", [])
Expand Down Expand Up @@ -470,7 +470,7 @@ def get_result_items(self, test, results, service_name=None, artifact_name=""):
fix_available=True,
service=service_name,
)
finding.unsaved_tags = [target_class]
finding.unsaved_tags = [tag for tag in (target_class,) if tag]
items.append(finding)

return items
Expand Down
6 changes: 4 additions & 2 deletions dojo/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ def clean_tags(value: str | list[str], exception_class: Callable = ValidationErr
return value

if isinstance(value, list):
# Replace ALL occurrences of problematic characters in each tag
return [TAG_PATTERN.sub("_", tag) for tag in value]
# Replace ALL occurrences of problematic characters in each tag.
# Parsers can emit None tags (e.g. optional report fields); drop them
# instead of crashing the import pipeline (TypeError in re.sub).
return [TAG_PATTERN.sub("_", tag) for tag in value if tag is not None]

if isinstance(value, str):
# Replace ALL occurrences of problematic characters in the tag
Expand Down
32 changes: 32 additions & 0 deletions unittests/test_validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from django.core.exceptions import ValidationError

from dojo.validators import clean_tags
from unittests.dojo_test_case import DojoTestCase


class TestCleanTags(DojoTestCase):

def test_clean_tags_string(self):
self.assertEqual("simple_tag", clean_tags("simple tag"))

def test_clean_tags_list(self):
self.assertEqual(["tag_one", "tag_two"], clean_tags(["tag one", "tag,two"]))

def test_clean_tags_empty_values(self):
self.assertEqual([], clean_tags([]))
self.assertEqual("", clean_tags(""))
self.assertIsNone(clean_tags(None))

def test_clean_tags_list_with_none_entries(self):
"""
Parsers can emit None tags (e.g. Trivy legacy reports without a
"Class" field). clean_tags must filter them out instead of raising
TypeError from the regex (see import pipeline crash in
default_importer._process_findings_internal).
"""
self.assertEqual(["os-pkgs"], clean_tags(["os-pkgs", None]))
self.assertEqual([], clean_tags([None, None]))

def test_clean_tags_invalid_type_raises(self):
with self.assertRaises(ValidationError):
clean_tags(42)
4 changes: 4 additions & 0 deletions unittests/tools/test_trivy_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def test_legacy_many_vulns(self):
parser = TrivyParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(len(findings), 93)
# Legacy reports have no "Class" field; tags must not contain None
# or the import pipeline crashes in clean_tags (TypeError)
for finding in findings:
self.assertNotIn(None, finding.unsaved_tags)
finding = findings[0]
self.assertEqual("Low", finding.severity)
self.assertEqual(1, len(finding.unsaved_vulnerability_ids))
Expand Down
Loading