Skip to content

Commit 7958375

Browse files
committed
chore: add security scan workflow (trivy)
1 parent b107e7e commit 7958375

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
name: Security scan
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
trivy_scan:
11+
name: Trivy Security Scan (Full)
12+
runs-on: ubuntu-latest
13+
outputs:
14+
trivy_high_found: ${{ steps.scan.outputs.trivy_high_found }}
15+
permissions:
16+
contents: write
17+
pull-requests: write
18+
steps:
19+
- name: Checkout Code
20+
uses: actions/checkout@v3
21+
22+
- name: Install Trivy
23+
run: |
24+
sudo apt update
25+
sudo apt install -y jq
26+
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | \
27+
sudo sh -s -- -b /usr/local/bin v0.70.0
28+
29+
- name: Sanitize branch name
30+
run: echo "SAFE_REF_NAME=${GITHUB_REF_NAME//\//-}" >> $GITHUB_ENV
31+
32+
- name: Run Trivy Filesystem Scan
33+
id: scan
34+
run: |
35+
set -euo pipefail
36+
echo "Running Trivy scan (HIGH/CRITICAL)..."
37+
mkdir -p tmp
38+
trivy fs --format json --severity HIGH,CRITICAL --output tmp/trivy.json .
39+
[[ -f tmp/trivy.json ]] || echo '{"Results":[]}' > tmp/trivy.json
40+
if ! jq -e '.Results and (.Results | length > 0)' tmp/trivy.json >/dev/null; then
41+
echo "No scan results available — likely no supported files found."
42+
echo "trivy_high_found=false" >> "$GITHUB_OUTPUT"
43+
exit 0
44+
fi
45+
count=$(jq -e '
46+
(.Results // [])
47+
| map(.Vulnerabilities? // [])
48+
| add
49+
| map(select(.Severity=="HIGH" or .Severity=="CRITICAL"))
50+
| length
51+
' tmp/trivy.json)
52+
if [[ "$count" -gt 0 ]]; then
53+
echo "trivy_high_found=true" >> "$GITHUB_OUTPUT"
54+
else
55+
echo "trivy_high_found=false" >> "$GITHUB_OUTPUT"
56+
fi
57+
58+
- name: Upload Trivy Report
59+
uses: actions/upload-artifact@v4
60+
with:
61+
name: trivy-json-${{ env.SAFE_REF_NAME }}
62+
path: tmp/trivy.json
63+
64+
- name: Generate PR Body (if vulnerabilities found)
65+
if: ${{ steps.scan.outputs.trivy_high_found == 'true' }}
66+
run: |
67+
echo "# 🛡️ Trivy Scan Report for branch \`${GITHUB_REF_NAME}\`" > tmp/pr-body.md
68+
jq -r '
69+
(.Results // [])
70+
| .[]
71+
| .Target as $file
72+
| (.Vulnerabilities? // [])
73+
| map(select(.Severity=="HIGH" or .Severity=="CRITICAL"))
74+
| .[]
75+
| "* File: \($file)\n • Vulnerability ID: \(.VulnerabilityID)\n • Pkg: \(.PkgName) \(.InstalledVersion)\n • Severity: \(.Severity)\n • Title: \(.Title)\n"
76+
' tmp/trivy.json >> tmp/pr-body.md
77+
78+
- name: Create Pull Request (if vulnerabilities found)
79+
if: ${{ github.event_name == 'push' && steps.scan.outputs.trivy_high_found == 'true' }}
80+
uses: peter-evans/create-pull-request@v5
81+
with:
82+
commit-message: 'chore: vulnerabilities detected by Trivy (HIGH/CRITICAL)'
83+
title: 'Trivy Vulnerability Report for branch ${{ github.ref_name }}'
84+
body-path: tmp/pr-body.md
85+
branch: auto/trivy-scan/${{ env.SAFE_REF_NAME }}
86+
base: ${{ github.ref_name }}
87+
delete-branch: true
88+
89+
- name: Close Stale Vulnerability PR (if clean)
90+
if: ${{ github.event_name == 'push' && steps.scan.outputs.trivy_high_found == 'false' }}
91+
env:
92+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
93+
run: |
94+
BRANCH="auto/trivy-scan/${{ env.SAFE_REF_NAME }}"
95+
PR_NUMBER=$(gh pr list --repo "${{ github.repository }}" --head "$BRANCH" --state open --json number --jq '.[0].number // empty')
96+
if [[ -n "$PR_NUMBER" ]]; then
97+
gh pr close "$PR_NUMBER" --repo "${{ github.repository }}" --comment "No HIGH/CRITICAL vulnerabilities found in latest scan on \`${{ github.ref_name }}\`. Closing report."
98+
fi
99+
100+
- name: Fail Job If Vulnerabilities Found
101+
if: ${{ steps.scan.outputs.trivy_high_found == 'true' }}
102+
run: exit 1

0 commit comments

Comments
 (0)