@@ -3,36 +3,47 @@ description: Performs Trivy Infrastructure as Code scanning and reporting
33
44inputs :
55 scan-ref :
6- description : ' Directory or file to scan'
6+ description : " Directory or file to scan"
77 required : false
8- default : ' ./terraform'
8+ default : " ./terraform"
9+
910 severity :
10- description : ' Comma-separated list of severity levels to report'
11+ description : " Comma-separated list of severity levels to report"
1112 required : false
12- default : ' HIGH,CRITICAL,MEDIUM,LOW,UNKNOWN'
13+ default : " HIGH,CRITICAL,MEDIUM,LOW,UNKNOWN"
14+
1315 trivy-config :
14- description : ' Path to Trivy configuration file'
16+ description : " Path to Trivy configuration file"
17+ required : false
18+ default : " trivy.yaml"
19+
20+ trivy-version :
21+ description : " Trivy version to install"
1522 required : false
16- default : ' trivy.yaml'
23+ default : " v0.69.2"
24+
1725 artifact-name :
18- description : ' Name for the uploaded artifact'
26+ description : " Name for the uploaded artifact"
1927 required : false
20- default : ' trivy-iac-scan-results'
28+ default : " trivy-iac-scan-results"
29+
2130 fail-on-critical-high :
22- description : ' Whether to fail the action on critical/high findings'
31+ description : " Whether to fail the action on critical/high findings"
2332 required : false
24- default : ' true'
33+ default : " true"
2534
2635outputs :
2736 critical-count :
28- description : ' Number of critical severity findings'
37+ description : " Number of critical severity findings"
2938 value : ${{ steps.report.outputs.crit }}
39+
3040 high-count :
31- description : ' Number of high severity findings'
41+ description : " Number of high severity findings"
3242 value : ${{ steps.report.outputs.high }}
43+
3344 report-path :
34- description : ' Path to the generated markdown report'
35- value : ' trivy_report.md'
45+ description : " Path to the generated markdown report"
46+ value : " trivy_report.md"
3647
3748runs :
3849 using : " composite"
@@ -49,44 +60,62 @@ runs:
4960 echo "config-arg=" >> "$GITHUB_OUTPUT"
5061 fi
5162
63+ - name : Setup Trivy
64+ uses : aquasecurity/setup-trivy@v0.2.5
65+ with :
66+ version : ${{ inputs.trivy-version }}
67+ cache : true
68+
69+ - name : Verify Trivy install
70+ shell : bash
71+ run : |
72+ set -euo pipefail
73+ which trivy
74+ trivy --version
75+
5276 - name : Trivy IaC scan
53- uses : aquasecurity/trivy-action@0.33.0
77+ uses : aquasecurity/trivy-action@0.34.2
78+ env :
79+ TRIVY_DEBUG : " true"
5480 with :
55- scan-type : ' config'
81+ skip-setup-trivy : " true"
82+ scan-type : " config"
5683 scan-ref : ${{ inputs.scan-ref }}
57- format : json
58- output : trivy-iac.json
84+ format : " json"
85+ output : " trivy-iac.json"
5986 severity : ${{ inputs.severity }}
60- exit-code : ' 0 ' # don't block the upload step
87+ exit-code : " 0 "
6188 hide-progress : true
6289 trivy-config : ${{ steps.trivy-config-check.outputs.config-arg }}
6390
6491 - name : Upload Trivy IaC Scan Artifact
92+ if : ${{ hashFiles('trivy-iac.json') != '' }}
6593 uses : actions/upload-artifact@v4
6694 with :
6795 name : ${{ inputs.artifact-name }}
6896 path : trivy-iac.json
6997
7098 - name : Build summary & counts
7199 id : report
100+ if : ${{ hashFiles('trivy-iac.json') != '' }}
72101 shell : bash
73102 run : |
103+ set -euo pipefail
104+
74105 jq -r '
75106 def clean: (.|tostring) | gsub("\\|"; "\\|") | gsub("\r?\n"; " ");
76107 def counts: reduce (.Results[]? | .Misconfigurations[]? | .Severity // empty) as $s
77108 ({CRITICAL:0,HIGH:0,MEDIUM:0,LOW:0,UNKNOWN:0}; .[$s]+=1);
78109
79110 counts as $c
80111 |
81- # ---- TOP BANNER (only if High/Critical present) ----
82112 (
83113 if (($c.CRITICAL + $c.HIGH) > 0) then
84114 "🚫 **Trivy gate:** **\($c.CRITICAL) Critical**, **\($c.HIGH) High** issue(s) found.\n\n"
85115 else
86116 "✅ **Trivy gate:** no Critical/High issues.\n\n"
87117 end
88118 )
89- # ---- SUMMARY REPORT ----
90119 + "### Trivy IaC (Terraform) Summary\n\n"
91120 + "| Severity | Count |\n|---|---|\n"
92121 + (["CRITICAL","HIGH","MEDIUM","LOW","UNKNOWN"]
@@ -102,31 +131,58 @@ runs:
102131 + "\n\n</details>\n"
103132 ' trivy-iac.json > trivy_report.md
104133
105- # Extract counts for gating/other steps
106- read CRIT HIGH < <(jq -r '
134+ COUNTS_TSV="$(jq -r '
107135 reduce (.Results[]? | .Misconfigurations[]? | .Severity // empty) as $s
108136 ({CRITICAL:0,HIGH:0,MEDIUM:0,LOW:0,UNKNOWN:0}; .[$s]+=1)
109- | "\(.CRITICAL) \(.HIGH)"
110- ' trivy-iac.json)
111- echo "crit=$CRIT" >> "$GITHUB_OUTPUT"
112- echo "high=$HIGH" >> "$GITHUB_OUTPUT"
137+ | [.CRITICAL, .HIGH] | @tsv
138+ ' trivy-iac.json)"
139+
140+ IFS=$'\t' read -r CRIT HIGH <<< "$COUNTS_TSV"
141+
142+ CRIT="${CRIT//[^0-9]/}"
143+ HIGH="${HIGH//[^0-9]/}"
144+
145+ echo "crit=${CRIT:-0}" >> "$GITHUB_OUTPUT"
146+ echo "high=${HIGH:-0}" >> "$GITHUB_OUTPUT"
147+
148+ - name : Default counts when no report exists
149+ id : report-defaults
150+ if : ${{ hashFiles('trivy-iac.json') == '' }}
151+ shell : bash
152+ run : |
153+ echo "crit=0" >> "$GITHUB_OUTPUT"
154+ echo "high=0" >> "$GITHUB_OUTPUT"
113155
114156 - name : Publish Trivy Summary
115- if : always()
157+ if : ${{ always() && hashFiles('trivy_report.md') != '' }}
116158 shell : bash
117159 run : cat trivy_report.md >> "$GITHUB_STEP_SUMMARY"
118160
119161 - name : Update Trivy PR comment
120- if : ${{ github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork }}
162+ if : ${{ github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && hashFiles('trivy_report.md') != '' }}
121163 uses : marocchino/sticky-pull-request-comment@v2
122164 with :
123165 header : trivy-iac-scan
124166 path : trivy_report.md
125167
126168 - name : Check Trivy Issue Thresholds
127- if : ${{ inputs.fail-on-critical-high == 'true' && (steps.report.outputs.crit != '0' || steps.report.outputs.high != '0') }}
169+ if : ${{ inputs.fail-on-critical-high == 'true' && hashFiles('trivy-iac.json') != '' }}
128170 shell : bash
129171 run : |
130- echo "Critical findings detected: ${{ steps.report.outputs.crit }}"
131- echo "High findings detected: ${{ steps.report.outputs.high }}"
132- exit 1
172+ set -euo pipefail
173+
174+ CRIT_RAW='${{ steps.report.outputs.crit }}'
175+ HIGH_RAW='${{ steps.report.outputs.high }}'
176+
177+ CRIT="${CRIT_RAW//[^0-9]/}"
178+ HIGH="${HIGH_RAW//[^0-9]/}"
179+
180+ CRIT="${CRIT:-0}"
181+ HIGH="${HIGH:-0}"
182+
183+ echo "Critical findings detected: ${CRIT}"
184+ echo "High findings detected: ${HIGH}"
185+
186+ if (( CRIT > 0 || HIGH > 0 )); then
187+ exit 1
188+ fi
0 commit comments