Repository navigation
Conversation
create_new_diff built the unchanged package set by filtering packages keyed by type/purl against added and removed packages keyed by artifact ID. The keys never matched, so every added package was also treated as unchanged, and under --strict-blocking its alerts were reported twice: once as new and once as existing. Against an empty baseline that doubled every finding in JSON, SARIF, Slack and GitLab output, and inflated the "EXISTING blocking issues" count in the summary and GitLab commit status. The exit code was not affected. Unchanged packages are now selected and keyed by artifact ID, which also lets transitive unchanged alerts resolve their introducing package. select_diff_alerts additionally skips an unchanged alert already listed as new, matching on purl and alert type like the rest of the diff. Bumps the version to 2.12.1.
PR SummaryLow Risk Overview
Release 2.12.1 with CHANGELOG and regression tests in Reviewed by Cursor Bugbot for commit fd2501d. Configure here. |
--strict-blocking
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit fd2501d. Configure here.
Issue.purl holds only name and version, so an npm and a PyPI package can share it. Keying the dedupe on purl and alert type alone would hide an existing PyPI alert behind a new npm alert with the same name, version and type. The regression tests now run Core.create_new_diff with the scan upload mocked out, instead of repeating its package assembly, so they fail if create_new_diff goes back to filtering unchanged packages by purl key.
--strict-blockingreports every alert on an added package twice, once as new and once as existing. Against an empty baseline, every finding doubles (70 alerts rendered as 140 JSON entries in an internal reproduction). The exit code is correct; only the rendered output and counts are wrong.Root Cause
create_new_diffbuilds the unchanged package set by filteringpackagesagainstadded_packagesandremoved_packages.packagesis keyed bytype/purl, but the other two are keyed by artifact ID, so the membership check never matches and every added package is also treated as unchanged. Its alerts land in bothdiff.new_alertsanddiff.unchanged_alerts, andselect_diff_alertsconcatenates the two.This isn't specific to empty baselines: any added package is affected. An empty baseline just makes every package an added one.
Affected under
--strict-blocking:Fix
Core.get_unchanged_packagesselects unchanged packages byPackage.idand keys the result by artifact ID, matching the added and removed dicts. That also letsget_source_dataresolvetopLevelAncestorsfor transitive unchanged alerts, which it couldn't do against purl keys.select_diff_alertsskips an unchanged alert already listed as new, matching on ecosystem, purl and alert type. The ecosystem is part of the key becauseIssue.purlholds only name and version, so an npm and a PyPI package can share it. Alerts without a purl are never deduped.Out of scope:
--strict-blockingexiting0against a real baseline despite existing blocking alerts. Thediff-scansAPI returns unchanged artifacts with emptyalerts, so that needs a backend change, tracked separately.Testing
tests/core/test_strict_blocking_duplicates.pyrunsCore.create_new_diffagainst a mocked diff response, with the scan upload mocked out, then checks the JSON and summary output. It covers an empty baseline, a real baseline with new and existing alerts, a failure on existing alerts alone, output without--strict-blocking, artifact-ID keying, and the dedupe, including the same purl in two ecosystems. 4 of the 7 tests fail onmain, and 3 fail ifcreate_new_diffalone goes back to the purl-keyed filter.uv run pytest: 605 passed.ruff checkis clean anduv lock --lockedis in sync.Public Changelog
Fixed
--strict-blockinglisting each finding on an added package twice in JSON, SARIF, Slack and GitLab output, and double-counting it as an existing issue in the summary.Fixes CE-498