111 lines
5.1 KiB
Markdown
111 lines
5.1 KiB
Markdown
# 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:
|
|
1. **Output File Handling:** The workflow assumes `results.json` is created, but `anchore/scan-action` with `output-format: json` might not produce this file by default without an explicit `output-file` parameter or capturing output.
|
|
2. **Parsing Logic:** If the file is missing, the `jq` parsing gracefully falls back to 0, masking the error.
|
|
3. **Failure Condition:** The failure step references `${{ steps.grype-scan.outputs.critical_count }}`, which likely does not exist on the `anchore/scan-action` step. 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 `cat` of 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
|
|
1. **Explicit Output File:** Modify the `anchore/scan-action` step to explicitly set `output-format: json` AND likely we should try to rely on the default behavior but *check* it.
|
|
*Actually, better practice:* The action supports `output-format` as 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.
|
|
2. **List Files:** Add `ls -la` after scan to see exactly what files are created.
|
|
|
|
### Phase 2: Fix Logic Errors
|
|
1. **Update "Fail on critical vulnerabilities" step**:
|
|
- Change `${{ steps.grype-scan.outputs.critical_count }}` to `${{ steps.vuln-summary.outputs.critical_count }}`.
|
|
2. **Robust `jq` parsing**:
|
|
- In `Process vulnerability results`, explicitly check for existence of `results.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 `tee` or `cat` to print the first few lines of the JSON to stdout for debugging logs.
|
|
|
|
### Phase 3: Validation
|
|
1. Run the workflow on a PR (or simulate via push).
|
|
2. Verify the PR comment shows actual numbers.
|
|
3. Verify the workflow fails if critical vulnerabilities are found (or we can lower the threshold to test).
|
|
|
|
## Detailed Changes
|
|
|
|
### `supply-chain-pr.yml`
|
|
|
|
```yaml
|
|
# ... 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 results` step fails if the scan output file is missing.
|
|
- [ ] Debug logging (ls -la) is present to confirm file placement.
|