1+ name : ' Organization Vulnerability Scan'
2+
3+ on :
4+ workflow_call :
5+ inputs :
6+ image-name :
7+ description : ' The full name of the Docker image to scan'
8+ required : true
9+ type : string
10+ secrets :
11+ TEAM_SLACK_WEBHOOK_URL :
12+ description : ' Slack webhook for team-specific vulnerability alerts'
13+ required : false
14+
15+ jobs :
16+ vulnerability-scan :
17+ name : Trivy Vulnerability Scan
18+ runs-on : ubuntu-latest
19+ permissions :
20+ contents : read
21+ packages : read
22+ security-events : write
23+
24+ env :
25+ SLACK_WEBHOOK_URL_SET : ${{ secrets.TEAM_SLACK_WEBHOOK_URL != '' }}
26+
27+ steps :
28+ - name : Checkout repository
29+ uses : actions/checkout@v4
30+
31+ - name : Log in to GitHub Container Registry
32+ uses : docker/login-action@v3
33+ with :
34+ registry : ghcr.io
35+ username : ${{ github.actor }}
36+ password : ${{ secrets.GITHUB_TOKEN }}
37+
38+ - name : Run Trivy for console output (All Vulnerabilities)
39+ uses : aquasecurity/trivy-action@master
40+ with :
41+ image-ref : ${{ inputs.image-name }}
42+ scan-type : ' image'
43+ severity : ' CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN'
44+ ignore-unfixed : false
45+ format : ' table'
46+ exit-code : ' 0'
47+
48+ - name : Run Trivy for console output (All Vulnerabilities) unfixed
49+ uses : aquasecurity/trivy-action@master
50+ with :
51+ image-ref : ${{ inputs.image-name }}
52+ scan-type : ' image'
53+ severity : ' CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN'
54+ ignore-unfixed : true
55+ format : ' table'
56+ exit-code : ' 0'
57+
58+ - name : Run Trivy for SARIF report (Fixed Vulnerabilities Only)
59+ id : trivy_sarif_scan
60+ uses : aquasecurity/trivy-action@master
61+ with :
62+ image-ref : ${{ inputs.image-name }}
63+ scan-type : ' image'
64+ severity : ' CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN'
65+ ignore-unfixed : true
66+ format : ' sarif'
67+ output : ' trivy-results.sarif'
68+ exit-code : ' 1'
69+ continue-on-error : true
70+
71+ # Check if the SARIF file has content
72+ - name : Check if SARIF report has content
73+ id : check_sarif
74+ run : |
75+ # If the trivy-results.sarif file exists and is larger than a few bytes (i.e., not empty),
76+ # set the output 'sarif_has_content' to true.
77+ if [ -s trivy-results.sarif ] && [ $(wc -c < trivy-results.sarif) -gt 2 ]; then
78+ echo "sarif_has_content=true" >> $GITHUB_OUTPUT
79+ else
80+ echo "sarif_has_content=false" >> $GITHUB_OUTPUT
81+ fi
82+ if : always() # Ensure this check runs even if the previous step failed
83+
84+ # Upload on condition
85+ - name : Upload Trivy SARIF report to GitHub Security
86+ # checks the output if ignore-unfixed is true throws an output
87+ if : steps.check_sarif.outputs.sarif_has_content == 'true'
88+ uses : github/codeql-action/upload-sarif@v3
89+ with :
90+ sarif_file : ' trivy-results.sarif'
91+
92+ - name : Send Slack Notification on Failure
93+ if : steps.trivy_sarif_scan.outcome == 'failure' && env.SLACK_WEBHOOK_URL_SET == 'true'
94+ 95+ with :
96+ payload : |
97+ {
98+ "blocks": [
99+ {
100+ "type": "section",
101+ "text": { "type": "mrkdwn", "text": "🚨 *Vulnerability Alert in `${{ github.repository }}`*" }
102+ },
103+ {
104+ "type": "section",
105+ "text": { "type": "mrkdwn", "text": "High or critical vulnerabilities with an available fix were detected." }
106+ },
107+ {
108+ "type": "actions",
109+ "elements": [ { "type": "button", "text": { "type": "plain_text", "text": "View Workflow Run" }, "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" } ]
110+ }
111+ ]
112+ }
113+ env :
114+ SLACK_WEBHOOK_URL : ${{ secrets.TEAM_SLACK_WEBHOOK_URL }}
115+ SLACK_WEBHOOK_TYPE : INCOMING_WEBHOOK
0 commit comments