name: PR Security Scan on: pull_request_target: types: [opened, synchronize, reopened] jobs: scan: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - name: Check out code uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 submodules: 'recursive' - name: Build the Docker image uses: docker/build-push-action@v5 with: context: . push: false load: true tags: pr_image:${{ github.sha }} - name: Run Trivy vulnerability scanner on image uses: aquasecurity/trivy-action@0.20.0 with: image-ref: 'pr_image:${{ github.sha }}' format: 'json' output: 'trivy-image-results.json' severity: 'CRITICAL,HIGH' - name: Run Trivy vulnerability scanner on source code uses: aquasecurity/trivy-action@0.20.0 with: scan-type: 'fs' scan-ref: '.' format: 'json' output: 'trivy-fs-results.json' severity: 'CRITICAL,HIGH' - name: Process Trivy scan results id: process-results uses: actions/github-script@v7 with: script: | const fs = require('fs'); let commentBody = '## Security Scan Results for PR\n\n'; function processResults(results, title) { let sectionBody = `### ${title}\n\n`; if (results.Results && results.Results.some(result => result.Vulnerabilities && result.Vulnerabilities.length > 0)) { sectionBody += '| Package | Version | Vulnerability | Severity |\n'; sectionBody += '|---------|---------|----------------|----------|\n'; const uniqueVulns = new Set(); results.Results.forEach(result => { if (result.Vulnerabilities) { result.Vulnerabilities.forEach(vuln => { const vulnKey = `${vuln.PkgName}-${vuln.InstalledVersion}-${vuln.VulnerabilityID}`; if (!uniqueVulns.has(vulnKey)) { uniqueVulns.add(vulnKey); sectionBody += `| ${vuln.PkgName} | ${vuln.InstalledVersion} | [${vuln.VulnerabilityID}](https://nvd.nist.gov/vuln/detail/${vuln.VulnerabilityID}) | ${vuln.Severity} |\n`; } }); } }); } else { sectionBody += '🎉 No vulnerabilities found!\n'; } return sectionBody; } try { const imageResults = JSON.parse(fs.readFileSync('trivy-image-results.json', 'utf8')); const fsResults = JSON.parse(fs.readFileSync('trivy-fs-results.json', 'utf8')); commentBody += processResults(imageResults, "Docker Image Scan Results"); commentBody += '\n'; commentBody += processResults(fsResults, "Source Code Scan Results"); } catch (error) { commentBody += `There was an error while running the security scan: ${error.message}\n`; commentBody += 'Please contact the core team for assistance.'; } core.setOutput('comment-body', commentBody); - name: Find Comment uses: peter-evans/find-comment@v3 id: fc with: issue-number: ${{ github.event.pull_request.number }} comment-author: 'github-actions[bot]' body-includes: Security Scan Results for PR - name: Create or update comment uses: peter-evans/create-or-update-comment@v3 with: issue-number: ${{ github.event.pull_request.number }} comment-id: ${{ steps.fc.outputs.comment-id }} body: ${{ steps.process-results.outputs.comment-body }} edit-mode: replace