diff --git a/.github/workflows/image-security-scan.yml b/.github/workflows/image-security-scan.yml index 0cfdc5e5..99804fb3 100644 --- a/.github/workflows/image-security-scan.yml +++ b/.github/workflows/image-security-scan.yml @@ -123,6 +123,12 @@ jobs: # visible, Renovate-trackable dependency instead of a value # hidden inside the action's own action.yaml default. version: v0.74.0 + # Without this, documented .trivyignore exceptions (see + # docs/image-scanning.md) are silently never applied here: this + # step previously omitted the input entirely, so approved, + # unexpired exceptions kept re-triggering duplicate scheduled-scan + # issues for the same already-tracked CVE. + trivyignores: .trivyignore image-ref: ${{ steps.ref.outputs.image-ref }} format: table output: scan-${{ matrix.image.name }}.txt diff --git a/.github/workflows/publish-images.yml b/.github/workflows/publish-images.yml index b2aa5fb4..0253f534 100644 --- a/.github/workflows/publish-images.yml +++ b/.github/workflows/publish-images.yml @@ -122,7 +122,7 @@ jobs: uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: version: v0.74.0 - ignorefile: .trivyignore + trivyignores: .trivyignore image-ref: cds/${{ matrix.image.name }}${{ matrix.image.variant != '' && format('-{0}', matrix.image.variant) || '' }}:scan format: table scanners: vuln @@ -284,7 +284,7 @@ jobs: uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: version: v0.74.0 - ignorefile: .trivyignore + trivyignores: .trivyignore image-ref: cds/${{ matrix.image.name }}${{ matrix.image.variant != '' && format('-{0}', matrix.image.variant) || '' }}:scan format: table scanners: vuln diff --git a/CHANGELOG.md b/CHANGELOG.md index 9aca5a37..b6879185 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ The format is based on Keep a Changelog. - Added a regression guard for #354: the image-policy finding IDs CDS-SEC-050/051/052 must still be emitted by `cli/image_verification.py` for a non-compliant Compose fixture, and none of the deleted IDs may reappear in the rule set. - Added a regression guard for #355: no `scope: ["none"]` security rule may be enabled in the bundled rule set. - Added a regression guard for #397: a `CDS_DB_PASSWORD` reference with a fallback value outside CDS-SEC-040's literal list is still caught by preflight insecure-default detection. +- `image-security-scan.yml`'s scheduled scan step never passed a `trivyignores` input to `trivy-action`, and `publish-images.yml`'s pre-push gate passed it under the wrong input name (`ignorefile` instead of `trivyignores`); both silently ignored `.trivyignore`, so the approved CVE-2026-53612/53613/53614 exceptions added in #484 never took effect and the daily scan kept refiling duplicate issues (#481, #482, #483, #485, #486, #487). ## [0.4.0] - 2026-08-11 diff --git a/tests/test_image_security_scan_workflow.py b/tests/test_image_security_scan_workflow.py index 63d54114..97beddcc 100644 --- a/tests/test_image_security_scan_workflow.py +++ b/tests/test_image_security_scan_workflow.py @@ -52,6 +52,10 @@ def test_vulnerability_scan_gates_on_high_and_critical(self) -> None: # exit-code must actually fail the job on a match, not just report. self.assertEqual(str(scan_step["with"]["exit-code"]), "1") self.assertEqual(scan_step["with"]["scanners"], "vuln") + # Without this, documented .trivyignore exceptions are silently + # never applied to the scheduled rescan (this input was previously + # missing entirely, see #481/#482/#483/#485/#486/#487). + self.assertEqual(scan_step["with"]["trivyignores"], ".trivyignore") # continue-on-error keeps the job status "success" after a scan # failure, so later steps whose `if:` lacks a status function (like # the issue-filing step) aren't implicitly skipped by GitHub Actions. diff --git a/tests/test_publish_images_workflow.py b/tests/test_publish_images_workflow.py index e7451d98..20f98602 100644 --- a/tests/test_publish_images_workflow.py +++ b/tests/test_publish_images_workflow.py @@ -83,7 +83,7 @@ def test_vuln_gate_fails_publish_on_high_critical(self) -> None: with_.get("image-ref"), "cds/${{ matrix.image.name }}${{ matrix.image.variant != '' && format('-{0}', matrix.image.variant) || '' }}:scan", ) - self.assertEqual(with_.get("ignorefile"), ".trivyignore") + self.assertEqual(with_.get("trivyignores"), ".trivyignore") self.assertNotIn("output", with_, "gate must stream findings to the run log") # Trivy CLI must be pinned the same way as the SBOM step. self.assertRegex(str(with_.get("version")), r"^v\d+\.\d+\.\d+$")