Skip to content

Commit aff8d4a

Browse files
use tags.add() instead of tags.set() on reimport (#14459)
* change logic to add tags instead of set * update unit tests * ruff --------- Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com>
1 parent b460aea commit aff8d4a

4 files changed

Lines changed: 56 additions & 4 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,6 @@ docs/.devcontainer/Dockerfile
149149
docs/LICENSE
150150
docs/.hugo_build.lock
151151
.cursor-rules
152+
153+
# claude etc
154+
MEMORY.md

dojo/importers/default_importer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,9 @@ def process_findings(
243243
# Parsers must use unsaved_tags to store tags, so we can clean them
244244
cleaned_tags = clean_tags(finding.unsaved_tags)
245245
if isinstance(cleaned_tags, list):
246-
finding.tags.set(cleaned_tags)
246+
finding.tags.add(*cleaned_tags)
247247
elif isinstance(cleaned_tags, str):
248-
finding.tags.set([cleaned_tags])
248+
finding.tags.add(cleaned_tags)
249249
# Process any files
250250
self.process_files(finding)
251251
# Process vulnerability IDs

dojo/importers/default_reimporter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -945,9 +945,9 @@ def finding_post_processing(
945945
if finding_from_report.unsaved_tags:
946946
cleaned_tags = clean_tags(finding_from_report.unsaved_tags)
947947
if isinstance(cleaned_tags, list):
948-
finding.tags.set(cleaned_tags)
948+
finding.tags.add(*cleaned_tags)
949949
elif isinstance(cleaned_tags, str):
950-
finding.tags.set([cleaned_tags])
950+
finding.tags.add(cleaned_tags)
951951
# Process any files
952952
if finding_from_report.unsaved_files:
953953
finding.unsaved_files = finding_from_report.unsaved_files

unittests/test_tags.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ def setUp(self):
279279
self.zap_sample5_filename = get_unit_tests_scans_path("zap") / "5_zap_sample_one.xml"
280280
self.generic_sample_with_tags_filename = get_unit_tests_scans_path("generic") / "generic_report1.json"
281281
self.generic_sample_with_more_tags_filename = get_unit_tests_scans_path("generic") / "generic_report1_more_tags.json"
282+
self.trivy_filename = get_unit_tests_scans_path("trivy") / "scheme_2_many_vulns.json"
282283

283284
def test_import_and_reimport_with_tags(self):
284285
"""Test that tags passed as import parameter are applied to the test."""
@@ -304,6 +305,54 @@ def test_import_and_reimport_with_tags(self):
304305
for tag in tags:
305306
self.assertIn(tag, response["tags"])
306307

308+
def test_manually_set_tags_preserved_on_reimport(self):
309+
"""
310+
Manually set tags on findings must survive a reimport.
311+
312+
Regression test for finding_post_processing() using tags.set() instead of
313+
tags.add(), which caused manually-set tags to be silently wiped when reimporting
314+
with parsers that populate unsaved_tags (Trivy, SARIF, SonarQube, etc.).
315+
"""
316+
# 1. Import a Trivy scan
317+
import0 = self.import_scan_with_params(
318+
self.trivy_filename,
319+
scan_type="Trivy Scan",
320+
minimum_severity="Info",
321+
)
322+
test_id = import0["test"]
323+
324+
# 2. Fetch findings and manually tag each one with "bla_bla"
325+
findings_before = self.get_test_findings_api(test_id)["results"]
326+
self.assertGreater(len(findings_before), 0, "Expected findings from Trivy scan")
327+
for finding in findings_before:
328+
self.patch_finding_api(finding["id"], {"tags": ["bla_bla"]})
329+
330+
# 3. Confirm the tag was applied before reimport
331+
findings_before = self.get_test_findings_api(test_id)["results"]
332+
for finding in findings_before:
333+
self.assertIn(
334+
"bla_bla",
335+
finding["tags"],
336+
f"Tag 'bla_bla' was not set on finding {finding['id']} before reimport",
337+
)
338+
339+
# 4. Reimport the same scan
340+
self.reimport_scan_with_params(
341+
test_id,
342+
self.trivy_filename,
343+
scan_type="Trivy Scan",
344+
minimum_severity="Info",
345+
)
346+
347+
# 5. Confirm manually set tags survived — reimport must not overwrite them
348+
findings_after = self.get_test_findings_api(test_id)["results"]
349+
for finding in findings_after:
350+
self.assertIn(
351+
"bla_bla",
352+
finding["tags"],
353+
f"Manually set tag 'bla_bla' was overwritten on finding {finding['id']} during reimport",
354+
)
355+
307356
def test_import_report_with_tags(self):
308357
"""Test that parser-generated tags on findings are preserved during import/reimport."""
309358
def assert_tags_in_findings(findings: list[dict], expected_finding_count: int, desired_tags: list[str]) -> None:

0 commit comments

Comments
 (0)