Merge branch 'main' into renovate/actions-cache-6.x
CI Tests / JS Unit Tests (pull_request) Successful in 9s
Philipp/Global-Workflows: Pre-commit Lint (Scoped) / pre-commit (pull_request) Successful in 2m2s
CI Tests / cross-check-mixed-sbom (sbom=true) (pull_request) Successful in 4m34s
CI Tests / cross-check-mixed-sbom (sbom=false) (pull_request) Successful in 5m16s
CI Tests / without-inbuild-sbom (sbom=false) (pull_request) Successful in 7m5s
CI Tests / without-inbuild-sbom (sbom=true) (pull_request) Successful in 2m55s
CI Tests / with-inbuild-sbom (sbom=false) (pull_request) Successful in 3m7s
CI Tests / with-inbuild-sbom (sbom=true) (pull_request) Successful in 2m24s

This commit is contained in:
Philipp committed 2026-09-15 00:32:49 +02:00
commit 8070a3c155
11 files changed
+500 -22

No files matched your search

+127 -5
View File
@@ -29,7 +29,7 @@ inputs:
required: false
default: 'true'
use-inbuild-sbom:
description: Whether to inspect and use built-in image SBOM attestations. If false, generates SBOM directly from images with Trivy.
description: Whether to inspect and use built-in image SBOM attestations. If false (recommended default), generates SBOMs directly with Trivy for maximum vulnerability detection fidelity. If true, extracts attestations without pulling layers (faster, but findings may differ from direct scans due to binary vs source package tracking; falls back to Trivy image scan if 0 CVEs detected).
required: false
default: 'false'
@@ -158,6 +158,12 @@ runs:
fi
echo "Configured platforms: ${PLATFORMS[*]:-(single platform fallback)}"
if [ "$use_inbuild" = "true" ]; then
echo "ℹ️ Strategy: Built-in SBOM attestation extraction enabled (Docker Scout / Syft). Skips container layer downloads for maximum speed."
echo "ℹ️ Note: Built-in SBOM vulnerability counts may differ from direct filesystem scans ('trivy image') due to binary vs. source package tracking."
else
echo "ℹ️ Strategy: Direct Trivy image scanning enabled (default). Inspects full container rootfs and package databases for maximum fidelity."
fi
for platform in "${PLATFORMS[@]}"; do
arch_tag=$(echo "$platform" | sed -e 's#^[a-zA-Z0-9_-]*/##' -e 's#/#-#g')
@@ -168,6 +174,7 @@ runs:
docker buildx imagetools inspect "${{ inputs.head-image }}" \
--format "{{ json (index .SBOM \"${platform}\").SPDX }}" > "sboms/head/sbom-${arch_tag}.spdx.json" 2>/dev/null || true
cleanup_file "sboms/head/sbom-${arch_tag}.spdx.json"
[ -f "sboms/head/sbom-${arch_tag}.spdx.json" ] && cp "sboms/head/sbom-${arch_tag}.spdx.json" "sboms/head/inbuild-sbom-${arch_tag}.spdx.json" 2>/dev/null || true
fi
if [ ! -f "sboms/head/sbom-${arch_tag}.spdx.json" ]; then
@@ -184,6 +191,7 @@ runs:
docker buildx imagetools inspect "${{ inputs.target-image }}" \
--format "{{ json (index .SBOM \"${platform}\").SPDX }}" > "sboms/target/sbom-${arch_tag}.spdx.json" 2>/dev/null || true
cleanup_file "sboms/target/sbom-${arch_tag}.spdx.json"
[ -f "sboms/target/sbom-${arch_tag}.spdx.json" ] && cp "sboms/target/sbom-${arch_tag}.spdx.json" "sboms/target/inbuild-sbom-${arch_tag}.spdx.json" 2>/dev/null || true
fi
if [ ! -f "sboms/target/sbom-${arch_tag}.spdx.json" ]; then
@@ -201,6 +209,7 @@ runs:
docker buildx imagetools inspect "${{ inputs.head-image }}" \
--format '{{ json .SBOM.SPDX }}' > sboms/head/sbom-default.spdx.json 2>/dev/null || true
cleanup_file sboms/head/sbom-default.spdx.json
[ -f sboms/head/sbom-default.spdx.json ] && cp sboms/head/sbom-default.spdx.json sboms/head/inbuild-sbom-default.spdx.json 2>/dev/null || true
fi
if [ ! -f sboms/head/sbom-default.spdx.json ]; then
@@ -217,6 +226,7 @@ runs:
docker buildx imagetools inspect "${{ inputs.target-image }}" \
--format '{{ json .SBOM.SPDX }}' > sboms/target/sbom-default.spdx.json 2>/dev/null || true
cleanup_file sboms/target/sbom-default.spdx.json
[ -f sboms/target/sbom-default.spdx.json ] && cp sboms/target/sbom-default.spdx.json sboms/target/inbuild-sbom-default.spdx.json 2>/dev/null || true
fi
if [ ! -f sboms/target/sbom-default.spdx.json ]; then
@@ -304,6 +314,32 @@ runs:
head_summary=()
target_summary=()
use_inbuild="${{ inputs.use-inbuild-sbom }}"
detect_distro() {
node -e '
const fs = require("fs");
try {
const data = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
let name, ver;
for (const pkg of (data.packages || [])) {
for (const ref of (pkg.externalRefs || [])) {
if (ref.referenceType === "purl" && ref.referenceLocator) {
const mName = ref.referenceLocator.match(/[?&]os_name=([^&]+)/);
const mVer = ref.referenceLocator.match(/[?&]os_version=([^&]+)/);
if (mName && mVer) {
name = mName[1];
ver = mVer[1];
break;
}
}
}
if (name && ver) break;
}
if (name && ver) console.log(name + "/" + ver);
} catch (e) {}
' "$1" 2>/dev/null || true
}
# 1. Scan Head SBOMs
if [ ${#head_sboms[@]} -eq 0 ]; then
@@ -316,9 +352,49 @@ runs:
err_log="cve-reports/head/cve-${arch}.err"
echo "Scanning head SBOM for architecture: $arch"
if trivy sbom --skip-version-check --format json --output "$out_json" "$f" 2>"$err_log"; then
distro_arg=""
if [ "$use_inbuild" = "true" ]; then
detected_distro=$(detect_distro "$f")
if [ -n "$detected_distro" ]; then
echo "Detected distribution '${detected_distro}' from in-build SBOM PURLs. Scanning with --distro."
distro_arg="--distro ${detected_distro}"
fi
fi
scan_success=false
if trivy sbom $distro_arg --skip-version-check --format json --output "$out_json" "$f" 2>"$err_log"; then
scan_success=true
fi
vuln_cnt=0
if [ -s "$out_json" ]; then
cnt=$(grep -c '"VulnerabilityID"' "$out_json" 2>/dev/null || true)
cnt=$(echo "$cnt" | tr -d '[:space:]')
[ -n "$cnt" ] && vuln_cnt="$cnt"
fi
# Fallback if in-build SBOM scan produced 0 CVEs (e.g. incompatible third-party format) or scan failed
if [ "$use_inbuild" = "true" ] && { [ "$scan_success" != "true" ] || [ "$vuln_cnt" -eq 0 ]; }; then
echo "::warning::In-build SBOM for head image (${arch}) yielded ${vuln_cnt} CVE findings. Falling back to direct Trivy image scan..."
t_plat="linux/${arch}"
[ "$arch" = "default" ] && t_plat=""
plat_arg=""
[ -n "$t_plat" ] && plat_arg="--platform $t_plat"
if trivy image --skip-version-check $plat_arg --format spdx-json --output "$f" "${{ inputs.head-image }}"; then
echo "Re-scanning head SBOM generated directly by Trivy..."
if trivy sbom --skip-version-check --format json --output "$out_json" "$f" 2>"$err_log"; then
scan_success=true
if [ -s "$out_json" ]; then
cnt=$(grep -c '"VulnerabilityID"' "$out_json" 2>/dev/null || true)
cnt=$(echo "$cnt" | tr -d '[:space:]')
[ -n "$cnt" ] && vuln_cnt="$cnt"
fi
fi
fi
fi
if [ "$scan_success" = "true" ]; then
if [ -s "$out_json" ]; then
vuln_cnt=$(grep -o '"VulnerabilityID"' "$out_json" 2>/dev/null | wc -l || echo 0)
if [ "$vuln_cnt" -eq 0 ]; then
echo "::warning::Head image architecture '${arch}' has 0 CVE findings. Verify that OS/packages were recognized."
head_summary+=(" - ${arch}: ⚠️ WARNING (0 vulnerability findings detected)")
@@ -350,9 +426,49 @@ runs:
err_log="cve-reports/target/cve-${arch}.err"
echo "Scanning target SBOM for architecture: $arch"
if trivy sbom --skip-version-check --format json --output "$out_json" "$f" 2>"$err_log"; then
distro_arg=""
if [ "$use_inbuild" = "true" ]; then
detected_distro=$(detect_distro "$f")
if [ -n "$detected_distro" ]; then
echo "Detected distribution '${detected_distro}' from in-build SBOM PURLs. Scanning with --distro."
distro_arg="--distro ${detected_distro}"
fi
fi
scan_success=false
if trivy sbom $distro_arg --skip-version-check --format json --output "$out_json" "$f" 2>"$err_log"; then
scan_success=true
fi
vuln_cnt=0
if [ -s "$out_json" ]; then
cnt=$(grep -c '"VulnerabilityID"' "$out_json" 2>/dev/null || true)
cnt=$(echo "$cnt" | tr -d '[:space:]')
[ -n "$cnt" ] && vuln_cnt="$cnt"
fi
# Fallback if in-build SBOM scan produced 0 CVEs (e.g. incompatible third-party format) or scan failed
if [ "$use_inbuild" = "true" ] && { [ "$scan_success" != "true" ] || [ "$vuln_cnt" -eq 0 ]; }; then
echo "::warning::In-build SBOM for target image (${arch}) yielded ${vuln_cnt} CVE findings. Falling back to direct Trivy image scan..."
t_plat="linux/${arch}"
[ "$arch" = "default" ] && t_plat=""
plat_arg=""
[ -n "$t_plat" ] && plat_arg="--platform $t_plat"
if trivy image --skip-version-check $plat_arg --format spdx-json --output "$f" "${{ inputs.target-image }}"; then
echo "Re-scanning target SBOM generated directly by Trivy..."
if trivy sbom --skip-version-check --format json --output "$out_json" "$f" 2>"$err_log"; then
scan_success=true
if [ -s "$out_json" ]; then
cnt=$(grep -c '"VulnerabilityID"' "$out_json" 2>/dev/null || true)
cnt=$(echo "$cnt" | tr -d '[:space:]')
[ -n "$cnt" ] && vuln_cnt="$cnt"
fi
fi
fi
fi
if [ "$scan_success" = "true" ]; then
if [ -s "$out_json" ]; then
vuln_cnt=$(grep -o '"VulnerabilityID"' "$out_json" 2>/dev/null | wc -l || echo 0)
if [ "$vuln_cnt" -eq 0 ]; then
echo "::warning::Target baseline image architecture '${arch}' has 0 CVE findings. Verify that OS/packages were recognized."
target_summary+=(" - ${arch}: ⚠️ WARNING (0 vulnerability findings detected)")
@@ -378,6 +494,12 @@ runs:
echo "================================================================================"
echo " CVE VULNERABILITY SCAN DIAGNOSTIC OVERVIEW "
echo "================================================================================"
if [ "$use_inbuild" = "true" ]; then
echo "Scan Strategy: Built-in OCI Attestation (Syft/Docker Scout) with distro detection"
else
echo "Scan Strategy: Direct Trivy Image Scan (Full rootfs & source package mapping)"
fi
echo "--------------------------------------------------------------------------------"
echo "HEAD Image: ${{ inputs.head-image }}"
for line in "${head_summary[@]}"; do
echo "$line"