From 6f988c1bd444ae8cf9f587af1f0bd984fd0b4c44 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:04:30 +0000 Subject: [PATCH 1/2] Initial plan From 8ee5126d42b9d7c504527f58efcaa2a3dd3be025 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:17:26 +0000 Subject: [PATCH 2/2] Fix container scan exit handling Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../workflows/daily-squid-image-scan.lock.yml | 31 ++++++++++++++----- .github/workflows/daily-squid-image-scan.md | 27 +++++++++++++--- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/.github/workflows/daily-squid-image-scan.lock.yml b/.github/workflows/daily-squid-image-scan.lock.yml index 56521350037..1f6f005f36e 100644 --- a/.github/workflows/daily-squid-image-scan.lock.yml +++ b/.github/workflows/daily-squid-image-scan.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"2fdca74fe22075f66004cc1d12d83c98bce3aee24e184763ac92e74333ec743c","body_hash":"7a1f8b7d3ba999bc2945954c493e41a43a33b260a3374e9b0d67958617da65db","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.73"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"152685b4f0cd2413c50576d7177b63b1ea7d54bcd367ad48a705623da70497a9","body_hash":"7a1f8b7d3ba999bc2945954c493e41a43a33b260a3374e9b0d67958617da65db","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.73"}} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.37","digest":"sha256:0d35e8682845f183c1c634699a8e8a6cbe2c271b867031410df74533243c5f67","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.37@sha256:0d35e8682845f183c1c634699a8e8a6cbe2c271b867031410df74533243c5f67"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.37","digest":"sha256:fc2970aadaeae05993e76697d29f03dc8bfb9248ff87a8f3d8b0975485a4b317","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.37@sha256:fc2970aadaeae05993e76697d29f03dc8bfb9248ff87a8f3d8b0975485a4b317"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.37","digest":"sha256:5abc51995e5901c5d1daeefc957301ee409980e2e607391ec22c06cb2513327b","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.37@sha256:5abc51995e5901c5d1daeefc957301ee409980e2e607391ec22c06cb2513327b"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.3","digest":"sha256:3c744710ea275cd5ee65db92a1099e0d980754bd9fafda9ce67704c67004dc83","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.3@sha256:3c744710ea275cd5ee65db92a1099e0d980754bd9fafda9ce67704c67004dc83"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.6.0","digest":"sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3","pinned_image":"ghcr.io/github/github-mcp-server:v1.6.0@sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -984,9 +984,15 @@ jobs: if [ ! -f /tmp/gh-aw/agent_output.json ]; then echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi - - if: always() + - env: + SCAN_JOB_RESULT: ${{ needs.scan_image.result }} + if: always() name: Enforce critical vulnerability and license gates run: |- + if [ "$SCAN_JOB_RESULT" != "success" ]; then + echo "::error::Image scan job concluded with ${SCAN_JOB_RESULT}." + exit 1 + fi summary="/tmp/gh-aw/agent/image-scan/summary.json" jq -e ' (.critical_vulnerabilities == 0) and @@ -1788,6 +1794,7 @@ jobs: image_tag=$(jq -r '.image' <<<"$image_entry") pinned_image=$(jq -r '.pinned_image' <<<"$image_entry") index_digest=$(jq -r '.digest' <<<"$image_entry") + echo "Scanning ${pinned_image}" image_errors="$output/${artifact_prefix}-errors.txt" image_platforms="$output/${artifact_prefix}-platforms.tsv" : > "$image_errors" @@ -1871,12 +1878,14 @@ jobs: if ! syft "${syft_args[@]}" "$immutable_image" \ -o "syft-json=${syft_json}" \ -o "spdx-json=${spdx_json}" > "$output/syft-${suffix}.txt" 2>&1; then + cat "$output/syft-${suffix}.txt" >&2 record_image_error "Syft failed to scan ${image_tag} for ${platform} at ${child_digest}." continue fi if ! GRYPE_DB_AUTO_UPDATE=false grype "sbom:${syft_json}" \ -o json > "$output/grype-${suffix}.json" 2> "$output/grype-${suffix}.stderr"; then + cat "$output/grype-${suffix}.stderr" >&2 record_image_error "Grype failed to produce JSON results for ${image_tag} on ${platform}." continue fi @@ -1894,34 +1903,42 @@ jobs: image_critical=$((image_critical + platform_critical)) image_fixable=$((image_fixable + platform_fixable)) + grype_exit=0 GRYPE_DB_AUTO_UPDATE=false grype "sbom:${syft_json}" \ - --fail-on critical -o table > "$output/grype-${suffix}.txt" 2>&1 - grype_exit=$? - if [ "$grype_exit" -ne 0 ] && [ "$grype_exit" -ne 1 ]; then + --fail-on critical -o table > "$output/grype-${suffix}.txt" 2>&1 || + grype_exit=$? + if [ "$grype_exit" -ne 0 ] && [ "$grype_exit" -ne 2 ]; then + cat "$output/grype-${suffix}.txt" >&2 record_image_error "Grype table scan failed unexpectedly for ${image_tag} on ${platform}." fi if ! grant list "$spdx_json" > "$output/grant-list-${suffix}.txt" 2>&1; then + cat "$output/grant-list-${suffix}.txt" >&2 record_image_error "Grant could not list licenses for ${image_tag} on ${platform}." fi grant_json="$output/grant-check-${suffix}.json" grant_stderr="$output/grant-check-${suffix}.stderr" + grant_exit=0 grant check --config .grant.yaml --output json "$spdx_json" \ - > "$grant_json" 2> "$grant_stderr" - grant_exit=$? + > "$grant_json" 2> "$grant_stderr" || + grant_exit=$? if ! jq -e '.run.targets | length > 0' "$grant_json" > /dev/null 2>&1; then + cat "$grant_stderr" >&2 record_image_error "Grant did not produce valid results for ${image_tag} on ${platform}." elif jq -e ' any(.run.targets[]; .evaluation.status == "error") ' "$grant_json" > /dev/null; then + cat "$grant_stderr" >&2 record_image_error "Grant encountered an evaluation error for ${image_tag} on ${platform}." elif jq -e ' any(.run.targets[]; .evaluation.status == "noncompliant") ' "$grant_json" > /dev/null; then image_license_rejected=true elif [ "$grant_exit" -ne 0 ]; then + cat "$grant_stderr" >&2 record_image_error "Grant failed unexpectedly for ${image_tag} on ${platform}." fi + echo "${image_tag} ${platform}: ${platform_total} vulnerabilities, ${platform_critical} critical, ${platform_fixable} fixable" done < "$image_platforms" total_vulnerabilities=$((total_vulnerabilities + image_total)) diff --git a/.github/workflows/daily-squid-image-scan.md b/.github/workflows/daily-squid-image-scan.md index 02fa00413fc..9935ce4c249 100644 --- a/.github/workflows/daily-squid-image-scan.md +++ b/.github/workflows/daily-squid-image-scan.md @@ -61,7 +61,13 @@ steps: post-steps: - name: Enforce critical vulnerability and license gates if: always() + env: + SCAN_JOB_RESULT: ${{ needs.scan_image.result }} run: | + if [ "$SCAN_JOB_RESULT" != "success" ]; then + echo "::error::Image scan job concluded with ${SCAN_JOB_RESULT}." + exit 1 + fi summary="/tmp/gh-aw/agent/image-scan/summary.json" jq -e ' (.critical_vulnerabilities == 0) and @@ -194,6 +200,7 @@ jobs: image_tag=$(jq -r '.image' <<<"$image_entry") pinned_image=$(jq -r '.pinned_image' <<<"$image_entry") index_digest=$(jq -r '.digest' <<<"$image_entry") + echo "Scanning ${pinned_image}" image_errors="$output/${artifact_prefix}-errors.txt" image_platforms="$output/${artifact_prefix}-platforms.tsv" : > "$image_errors" @@ -277,12 +284,14 @@ jobs: if ! syft "${syft_args[@]}" "$immutable_image" \ -o "syft-json=${syft_json}" \ -o "spdx-json=${spdx_json}" > "$output/syft-${suffix}.txt" 2>&1; then + cat "$output/syft-${suffix}.txt" >&2 record_image_error "Syft failed to scan ${image_tag} for ${platform} at ${child_digest}." continue fi if ! GRYPE_DB_AUTO_UPDATE=false grype "sbom:${syft_json}" \ -o json > "$output/grype-${suffix}.json" 2> "$output/grype-${suffix}.stderr"; then + cat "$output/grype-${suffix}.stderr" >&2 record_image_error "Grype failed to produce JSON results for ${image_tag} on ${platform}." continue fi @@ -300,34 +309,42 @@ jobs: image_critical=$((image_critical + platform_critical)) image_fixable=$((image_fixable + platform_fixable)) + grype_exit=0 GRYPE_DB_AUTO_UPDATE=false grype "sbom:${syft_json}" \ - --fail-on critical -o table > "$output/grype-${suffix}.txt" 2>&1 - grype_exit=$? - if [ "$grype_exit" -ne 0 ] && [ "$grype_exit" -ne 1 ]; then + --fail-on critical -o table > "$output/grype-${suffix}.txt" 2>&1 || + grype_exit=$? + if [ "$grype_exit" -ne 0 ] && [ "$grype_exit" -ne 2 ]; then + cat "$output/grype-${suffix}.txt" >&2 record_image_error "Grype table scan failed unexpectedly for ${image_tag} on ${platform}." fi if ! grant list "$spdx_json" > "$output/grant-list-${suffix}.txt" 2>&1; then + cat "$output/grant-list-${suffix}.txt" >&2 record_image_error "Grant could not list licenses for ${image_tag} on ${platform}." fi grant_json="$output/grant-check-${suffix}.json" grant_stderr="$output/grant-check-${suffix}.stderr" + grant_exit=0 grant check --config .grant.yaml --output json "$spdx_json" \ - > "$grant_json" 2> "$grant_stderr" - grant_exit=$? + > "$grant_json" 2> "$grant_stderr" || + grant_exit=$? if ! jq -e '.run.targets | length > 0' "$grant_json" > /dev/null 2>&1; then + cat "$grant_stderr" >&2 record_image_error "Grant did not produce valid results for ${image_tag} on ${platform}." elif jq -e ' any(.run.targets[]; .evaluation.status == "error") ' "$grant_json" > /dev/null; then + cat "$grant_stderr" >&2 record_image_error "Grant encountered an evaluation error for ${image_tag} on ${platform}." elif jq -e ' any(.run.targets[]; .evaluation.status == "noncompliant") ' "$grant_json" > /dev/null; then image_license_rejected=true elif [ "$grant_exit" -ne 0 ]; then + cat "$grant_stderr" >&2 record_image_error "Grant failed unexpectedly for ${image_tag} on ${platform}." fi + echo "${image_tag} ${platform}: ${platform_total} vulnerabilities, ${platform_critical} critical, ${platform_fixable} fixable" done < "$image_platforms" total_vulnerabilities=$((total_vulnerabilities + image_total))