1+ # This is a reusable workflow for scanning container images using Anchore's vulnerability scanner.
2+ # It can be called from other workflows to scan any container image and report findings to GitHub Security tab.
3+ name : Scan Container Image
4+
5+ # Define this as a reusable workflow that other workflows can call
6+ on :
7+ workflow_call :
8+ # Define the inputs that callers must/can provide
9+ inputs :
10+ image :
11+ required : true
12+ type : string
13+ description : ' Container image to scan (format: image:tag)'
14+ severity-cutoff :
15+ required : false
16+ type : string
17+ default : ' medium'
18+ description : ' Minimum severity to report (critical, high, medium, low, negligible)'
19+ fail-build :
20+ required : false
21+ type : boolean
22+ default : false
23+ description : ' Fail the workflow if vulnerabilities are found'
24+ platform :
25+ required : false
26+ type : string
27+ default : ' linux/amd64'
28+ description : ' Platform to scan (e.g., linux/amd64, linux/arm64)'
29+
30+ permissions : {} # Remove all permissions by default
31+
32+ jobs :
33+ scan :
34+ name : Scan Image
35+ runs-on : ubuntu-latest
36+ timeout-minutes : 30 # Default timeout for the job
37+ # Permissions required for security scanning and reporting
38+ permissions :
39+ security-events : write # Needed to upload SARIF results
40+ contents : read # Needed to read workflow files
41+
42+ steps :
43+ # Extract and normalize image details for use in later steps
44+ # Handles cases where tag might be missing (defaults to 'latest')
45+ # Creates a safe name for use in filenames and categories
46+ - name : Extract image details
47+ id : image_details
48+ run : |
49+ IMAGE_NAME=$(echo "${{ inputs.image }}" | cut -d':' -f1)
50+ IMAGE_TAG=$(echo "${{ inputs.image }}" | cut -d':' -f2)
51+ [[ "$IMAGE_TAG" == "$IMAGE_NAME" ]] && IMAGE_TAG="latest"
52+ SAFE_NAME=$(echo "${IMAGE_NAME}-${IMAGE_TAG}" | sed 's/[\/:]/-/g')
53+ echo "image_name=${IMAGE_NAME}" >> $GITHUB_OUTPUT
54+ echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
55+ echo "safe_name=${SAFE_NAME}" >> $GITHUB_OUTPUT
56+
57+ # Run Anchore vulnerability scanner on the specified image
58+ # Outputs findings in SARIF format for GitHub security dashboard
59+ - name : Scan image with Anchore
60+ uses : anchore/scan-action@v6
61+ id : scan
62+ with :
63+ image : " ${{ inputs.image }}"
64+ fail-build : ${{ inputs.fail-build }}
65+ severity-cutoff : ${{ inputs.severity-cutoff }}
66+ output-format : sarif
67+ platform : ${{ inputs.platform }}
68+
69+ # Enrich the SARIF output with additional metadata about the scanned image
70+ # This helps with tracking and identifying scan results in GitHub Security tab
71+ - name : Enrich SARIF with image metadata
72+ run : |
73+ # Install jq for JSON processing
74+ sudo apt-get update && sudo apt-get install -y jq
75+
76+ # Add metadata to SARIF using jq
77+ # This includes image details, scan time, and repository information
78+ jq --arg imageRef "${{ inputs.image }}" \
79+ --arg repo "${{ steps.image_details.outputs.image_name }}" \
80+ --arg name "${{ steps.image_details.outputs.image_name }}" \
81+ --arg tag "${{ steps.image_details.outputs.image_tag }}" \
82+ --arg scanTime "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
83+ --arg platform "${{ inputs.platform }}" \
84+ '.runs[0].properties = {
85+ "imageRef": $imageRef,
86+ "repository": $repo,
87+ "scanTime": $scanTime,
88+ "platform": $platform,
89+ "imageMetadata": {
90+ "name": $name,
91+ "tag": $tag
92+ }
93+ }' results.sarif > enriched-results.sarif
94+
95+ mv enriched-results.sarif results.sarif
96+
97+ # Upload the SARIF results to GitHub Security tab
98+ # Note: This uploads to the repository where the workflow runs, not the image source
99+ - name : Upload SARIF file
100+ uses : github/codeql-action/upload-sarif@v3
101+ with :
102+ sarif_file : results.sarif
103+ # Create a unique category for each image to separate findings
104+ category : " container-scan-${{ steps.image_details.outputs.safe_name }}"
105+
106+ # Archive the SARIF results as an artifact for later reference
107+ # Useful for debugging or historical analysis
108+ - name : Archive scan results
109+ uses : actions/upload-artifact@v4
110+ with :
111+ name : " sarif-${{ steps.image_details.outputs.safe_name }}"
112+ path : results.sarif
113+ retention-days : 365
0 commit comments