Forced workflow failure if scan results are missing (prevents false negatives) Fixed "Fail on critical" step to use calculated counts instead of missing action outputs Added debug logging and file verification for Grype scans Refactored shell scripts to prevent injection vulnerabilities
5.1 KiB
5.1 KiB
Plan: Fix Supply Chain Vulnerability Reporting
Objective
Fix the supply-chain-pr.yml workflow where PR comments report 0 vulnerabilities despite known CVEs, and ensure the workflow correctly fails on critical vulnerabilities.
Context
The current workflow uses anchore/scan-action to scan for vulnerabilities. However, there are potential issues with:
- Output File Handling: The workflow assumes
results.jsonis created, butanchore/scan-actionwithoutput-format: jsonmight not produce this file by default without an explicitoutput-fileparameter or capturing output. - Parsing Logic: If the file is missing, the
jqparsing gracefully falls back to 0, masking the error. - Failure Condition: The failure step references
${{ steps.grype-scan.outputs.critical_count }}, which likely does not exist on theanchore/scan-actionstep. It should reference the calculated output from the parsing step.
Research & Diagnosis Steps
1. Debug Output paths
We need to verify if results.json is actually generated.
- Action: Add a step to list files in the workspace immediately after the scan.
- Action: Add a debug
catof the results file if it exists, or header of it.
2. Verify anchore/scan-action behavior
The anchore/scan-action (v7.3.2) documentation suggests that output-format is used, but typically it defaults to results.[format]. However, explicit output-file prevents ambiguity.
Implementation Plan
Phase 1: Robust Path & Debugging
- Explicit Output File: Modify the
anchore/scan-actionstep to explicitly setoutput-format: jsonAND likely we should try to rely on the default behavior but check it. Actually, better practice: The action supportsoutput-formatas a list. If we want a file, we usually just look for it. Correction: We will explicitly check for the file and fail if missing, rather than defaulting to 0. - List Files: Add
ls -laafter scan to see exactly what files are created.
Phase 2: Fix Logic Errors
- Update "Fail on critical vulnerabilities" step:
- Change
${{ steps.grype-scan.outputs.critical_count }}to${{ steps.vuln-summary.outputs.critical_count }}.
- Change
- Robust
jqparsing:- In
Process vulnerability results, explicitly check for existence ofresults.json(or whatever the action outputs). - If missing, EXIT 1 instead of setting counts to 0. This forces us to fix the path issue rather than silently passing.
- Use
teeorcatto print the first few lines of the JSON to stdout for debugging logs.
- In
Phase 3: Validation
- Run the workflow on a PR (or simulate via push).
- Verify the PR comment shows actual numbers.
- Verify the workflow fails if critical vulnerabilities are found (or we can lower the threshold to test).
Detailed Changes
supply-chain-pr.yml
# ... inside steps ...
- name: Scan for vulnerabilities
if: steps.set-target.outputs.image_name != ''
uses: anchore/scan-action@7037fa011853d5a11690026fb85feee79f4c946c # v7.3.2
id: grype-scan
with:
sbom: sbom.cyclonedx.json
fail-build: false
output-format: json
# We might need explicit output selection implies asking for 'json' creates 'results.json'
- name: Debug Output Files
if: steps.set-target.outputs.image_name != ''
run: |
echo "📂 Listing workspace files:"
ls -la
- name: Process vulnerability results
if: steps.set-target.outputs.image_name != ''
id: vuln-summary
run: |
# The scan-action output behavior verification
JSON_RESULT="results.json"
SARIF_RESULT="results.sarif"
# [NEW] Check if scan actually produced output
if [[ ! -f "$JSON_RESULT" ]]; then
echo "❌ Error: $JSON_RESULT not found!"
echo "Available files:"
ls -la
exit 1
fi
mv "$JSON_RESULT" grype-results.json
# Debug content (head)
echo "📄 Grype JSON Preview:"
head -n 20 grype-results.json
# ... existing renaming for sarif ...
# ... existing jq logic, but remove 'else' block for missing file since we exit above ...
# ...
- name: Fail on critical vulnerabilities
if: steps.set-target.outputs.image_name != ''
run: |
# [FIX] Use the output from the summary step, NOT the scan step
CRITICAL_COUNT="${{ steps.vuln-summary.outputs.critical_count }}"
if [[ "${CRITICAL_COUNT}" -gt 0 ]]; then
echo "🚨 Found ${CRITICAL_COUNT} CRITICAL vulnerabilities!"
echo "Please review the vulnerability report and address critical issues before merging."
exit 1
fi
Acceptance Criteria
- Workflow "Fail on critical vulnerabilities" uses
steps.vuln-summary.outputs.critical_count. Process vulnerability resultsstep fails if the scan output file is missing.- Debug logging (ls -la) is present to confirm file placement.