Container images accumulate CVEs between builds — a base image pinned three months ago may carry critical kernel or libc vulnerabilities exploitable at runtime (NIST 800-53 SI-3, CWE-1357). Without automated scanning in CI/CD, vulnerable images reach production silently. SSDF 800-218 RV.1.3 requires continuous vulnerability monitoring of software components. CIS Docker 4.7 mandates scanning. A pipeline that scans but allows critical findings to pass with --exit-code 0 provides no protection — the gate must block deployment when high or critical CVEs are present.
High because unscanned images deliver known-CVE code to production silently, and most container exploits target CVEs that public scanners would have caught before deployment.
Add Trivy to every image-building pipeline in .github/workflows/build.yml and block deployment on HIGH or CRITICAL findings:
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.IMAGE }}:${{ env.TAG }}
exit-code: '1'
severity: 'HIGH,CRITICAL'
format: 'table'
For Snyk users: snyk container test <image:tag> --severity-threshold=high --fail-on=all. The key requirement is exit-code: 1 (Trivy) or equivalent — without it, findings are logged but the pipeline succeeds and the vulnerable image ships.
ID: infrastructure-hardening.container-image-security.image-scanning
Severity: high
What to look for: List all CI/CD configuration files (.github/workflows/*.yml, .gitlab-ci.yml, Jenkinsfile, etc.) and for each, check whether a vulnerability scanning step (Trivy, Snyk, Clair, or Aqua) is included. Count the total CI/CD pipelines that build images and how many include scanning. Verify scanning fails the pipeline on at least critical-severity CVEs.
Pass criteria: 100% of CI/CD pipelines that build container images include a vulnerability scanning step using Trivy, Snyk, or equivalent that runs on every image build. The pipeline fails or blocks deployment on at least critical and high-severity CVEs (minimum severity threshold of high). Report: "X of Y image-building pipelines include vulnerability scanning."
Fail criteria: No vulnerability scanning configured in CI/CD, scanning only runs manually or ad-hoc, or pipeline does not fail on critical/high CVEs.
Do NOT pass when: Scanning is present but configured with --exit-code 0 or equivalent that allows critical CVEs to pass silently — the pipeline must actually block on findings.
Skip (N/A) when: The project does not have CI/CD or container images.
Cross-reference: The from-official-pinned check ensures base images are pinned, which reduces the surface area that scanning must cover.
Detail on fail: Quote the CI/CD config path. Example: "No Trivy or Snyk step found in .github/workflows/build.yml. Images are built but not scanned." or "Trivy scanning present but pipeline does not fail on critical CVEs — results are only logged"
Remediation: Automate vulnerability scanning to catch CVEs before deployment:
# .github/workflows/build.yml
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.IMAGE_NAME }}:${{ env.TAG }}
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
Or with Snyk:
snyk container test <image:tag> --severity-threshold=high