# CVE Differential A self-contained Gitea and GitHub Actions composite action that extracts multi-platform SBOM attestations from container images, runs vulnerability scans with [Trivy](https://github.com/aquasecurity/trivy), and produces a set-based CVE delta report between a head image and a target baseline image. --- ## ✨ Features - **Dynamic Multi-Platform Support**: Automatically discovers and scans all architectures present in container images, or iterates over an explicit list of target architectures. - **Fast Attestation Extraction with Automatic Fallback**: Uses `docker buildx imagetools inspect` to extract platform-specific SBOMs directly from registry manifest indices. If attestations are missing or produce 0 CVE findings (common when third-party generators omit OS qualifiers in SPDX), it automatically falls back to generating SBOMs directly with Trivy per architecture. - **Set-Based Differential Analysis**: Categorizes vulnerabilities into: - 🔴 **Introduced Vulnerabilities** (newly added in this branch / commit) - 🟢 **Fixed Vulnerabilities** (present in target baseline, resolved in this branch) - ⚪ **Unchanged Vulnerabilities** (pre-existing in target baseline) - **Secure & Unit Tested**: Verified Trivy binary downloads against static SHA256 checksum lockfiles, single-step unified caching, and comprehensive native unit tests (`node:test`). --- ## 📥 Inputs | Input | Description | Required | Default | | :--- | :--- | :--- | :--- | | `head-image` | Head container image reference to scan (e.g. `registry.example.com/repo:git-sha`) | **Yes** | — | | `target-image` | Target baseline container image reference to compare against (e.g. `registry.example.com/repo:latest`) | **Yes** | — | | `target-branch` | Target branch name for report headings | No | `main` | | `architectures` | Comma-separated architectures/platforms to scan (e.g. `amd64,arm64`). If omitted, scans all architectures present in the image. | No | _(all)_ | | `output-delta` | Output path for the CVE delta Markdown report | No | `cve-delta.md` | | `output-summary` | Output path for the full vulnerability Markdown summary | No | `cve-summary.md` | | `write-summary` | Whether to append the generated reports to the job summary (`$GITHUB_STEP_SUMMARY`) | No | `true` | | `use-inbuild-sbom` | Whether to inspect and use built-in image SBOM attestations. If false, generates SBOMs directly with Trivy. If true, extracts attestations and automatically falls back to Trivy image generation if 0 CVEs are detected | No | `false` | --- ## 📤 Outputs | Output | Description | | :--- | :--- | | `delta-report` | Path to the generated CVE delta Markdown report | | `summary-report` | Path to the full vulnerability Markdown summary report | --- ## 🔍 Built-in SBOM Attestations vs. Trivy Direct Scanning (Syft vs. Trivy) This action supports two modes for obtaining SBOMs: ### 1. Direct Image Scanning with Trivy (`use-inbuild-sbom: false` — Default & Recommended) By default, the action uses `trivy image --format spdx-json` to generate the SBOM directly from the container images: - **Full Filesystem Fidelity**: Inspects the entire flattened root filesystem, reading `/etc/os-release` and native package databases (e.g. `/var/lib/dpkg/status`, RPM databases, apk). - **Accurate OS & Language Package Detection**: Successfully catalogs both OS packages (Debian, Alpine, RHEL, etc.) and application dependencies (Python, Node.js, Go, etc.). - **Symmetric, Apples-to-Apples Comparisons**: Both `head` and `target` images are analyzed using the identical Trivy engine and vulnerability database, preventing skewed diffs. ### 2. Built-in Attestation Extraction with Resilient Fallback (`use-inbuild-sbom: true`) When enabled, the action extracts SBOM attestations attached to the container image using `docker buildx imagetools inspect`: - **Speed**: Extracts the SBOM JSON metadata directly from the registry manifest index in seconds without pulling image layer blobs. - **Underlying Generator (Syft / Docker Scout)**: Docker Buildx (`sbom: true`) uses BuildKit's embedded Syft scanner (`moby/buildkit-syft-scanner`). - **Resilient Fallback**: If an extracted in-build SBOM scan produces 0 CVE findings (a common issue when third-party generators omit OS distribution qualifiers from SPDX packages) or if scanning fails, the action **automatically falls back** to running `trivy image --platform "$platform" --format spdx-json` directly on the image. This guarantees that vulnerability scans never fail silently or report false zeros. - **Audit Copies**: The action preserves copies of both the raw extracted in-build SBOM (`inbuild-sbom-*.spdx.json`) and the final scanned SBOM (`sbom-*.spdx.json`) for auditing and debugging. > [!TIP] > Setting `use-inbuild-sbom: 'false'` remains the recommended default for maximum accuracy and cross-platform consistency. If you choose to enable `use-inbuild-sbom: 'true'`, the built-in fallback ensures full coverage even when third-party attestations lack OS package metadata. --- ## 🚀 Usage Example ```yaml jobs: build-and-scan: runs-on: ubuntu-latest steps: - name: Build and Push Head Container Image uses: docker/build-push-action@v5 with: context: . push: true tags: registry.example.com/my-app:git-${{ github.sha }} - name: Compare Vulnerabilities (Head vs Target) uses: https://git.horstenkamp.eu/Philipp/cve-differential.git@main with: head-image: registry.example.com/my-app:git-${{ github.sha }} target-image: registry.example.com/my-app:latest target-branch: ${{ github.base_ref || 'main' }} ``` --- ## 📄 License MIT