CVE Check #860
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: CVE Check | |
# This check can be executed locally as follows: | |
# | |
# Install Trivy, see https://aquasecurity.github.io/trivy/v0.18.3/installation/ | |
# $ brew install aquasecurity/trivy/trivy | |
# | |
# Lock dependencies | |
# $ ./gradlew resolveAndLockAll --write-locks | |
# | |
# Check for vulnerabilities | |
# $ trivy fs -s CRITICAL --scanners vuln . | |
# "CRITICAL" can be "MEDIUM,HIGH,CRITICAL" as well | |
# | |
# Remove created lockfiles: | |
# $ find . -name gradle.lockfile -delete | |
on: | |
schedule: | |
- cron: "23 4 * * *" | |
jobs: | |
trivy-vulnerability-check: | |
timeout-minutes: 30 | |
runs-on: ubuntu-latest | |
outputs: | |
payload_matrix: ${{ steps.set-payload-matrix.outputs.payload_matrix }} | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 | |
- name: Set up JDK 17 | |
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 | |
with: | |
distribution: 'temurin' | |
java-version: 17 | |
cache: 'gradle' | |
- name: Create Gradle lockfiles | |
run: ./gradlew resolveAndLockAll --write-locks | |
- name: Check for vulnerabilities | |
uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # v0.22.0 | |
id: cve_check | |
with: | |
scan-type: 'fs' | |
scanners: 'vuln' | |
format: 'json' | |
scan-ref: '.' | |
severity: 'MEDIUM,HIGH,CRITICAL' | |
exit-code: '1' | |
ignore-policy: '.github/workflows/ignore-policy.rego' | |
output: 'cve-result.json' | |
- name: Prepare CVE Slack payload | |
if: failure() | |
run: | | |
node -e ' | |
const fs = require("fs"); | |
const cveResult = JSON.parse(fs.readFileSync("./cve-result.json")); | |
const getColoredCircle = severity => { | |
switch (severity) { | |
case "CRITICAL": | |
return ":red_circle:" | |
case "HIGH": | |
return ":large_orange_circle:" | |
case "MEDIUM": | |
return ":large_yellow_circle:" | |
default: | |
return "" | |
} | |
}; | |
let output = { | |
blocks: [ | |
{ | |
type: "header", | |
text: { | |
type: "plain_text", | |
text: "${{ github.event.repository.name }}", | |
emoji: true, | |
}, | |
}, | |
], | |
}; | |
cveResult.Results.filter( | |
(result) => result.Vulnerabilities !== undefined | |
).forEach((result) => { | |
output.blocks.push({type: "divider"}); | |
output.blocks.push({ | |
type: "section", | |
text: { | |
type: "mrkdwn", | |
text: `*${result.Target}*`, | |
}, | |
}); | |
result.Vulnerabilities.forEach((vuln) => { | |
output.blocks.push({ | |
type: "section", | |
fields: [ | |
{ | |
type: "mrkdwn", | |
text: `*Severity:*\n ${getColoredCircle(vuln.Severity)} ${vuln.Severity}`, | |
}, | |
{ | |
type: "mrkdwn", | |
text: `*Dependency:*\n${vuln.PkgName}:${vuln.InstalledVersion}`, | |
}, | |
{ | |
type: "mrkdwn", | |
text: `*Since*:\n ${vuln.PublishedDate}`, | |
}, | |
{ | |
type: "mrkdwn", | |
text: `*VulnerabilityID*:\n <${vuln.PrimaryURL}|${vuln.VulnerabilityID}>`, | |
}, | |
], | |
}); | |
}); | |
}); | |
const chunkSize = 50; // the Slack API is limited to 50 block items | |
let fileCount = 0; | |
for (let i = 0; i < output.blocks.length; i += chunkSize) { | |
const chunk = {blocks: output.blocks.slice(i, i + chunkSize)}; | |
try { | |
fs.writeFileSync(`./cve_slack_payload_${fileCount++}.json`, JSON.stringify(chunk)) | |
} catch (err) { | |
console.error(err); | |
} | |
} | |
' | |
- id: set-payload-matrix | |
if: failure() | |
run: | | |
files_array=$(ls cve_slack_payload_*[0-9]*.json | jq -R -s -c 'split("\n")[:-1]') | |
payload_matrix=$(jq -cn --argjson files "$files_array" '{file: $files}') | |
echo "payload_matrix=$payload_matrix" >> "$GITHUB_OUTPUT" | |
- name: Upload CVE files | |
if: failure() | |
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 | |
with: | |
name: cves | |
path: cve_slack_payload_*.json | |
post-vulnerabilities-to-slack: | |
if: failure() | |
needs: trivy-vulnerability-check | |
timeout-minutes: 30 | |
runs-on: ubuntu-latest | |
strategy: | |
max-parallel: 1 | |
matrix: ${{ fromJson(needs.trivy-vulnerability-check.outputs.payload_matrix) }} | |
steps: | |
- name: Download files | |
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 | |
with: | |
name: cves | |
- name: Notify CVEs in Slack | |
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 | |
env: | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
with: | |
channel-id: 'C05NM8419JM' # sda-dropwizard-commons-security | |
payload-file-path: ${{ matrix.file }} | |
post-success-to-slack: | |
if: success() | |
needs: trivy-vulnerability-check | |
timeout-minutes: 30 | |
runs-on: ubuntu-latest | |
steps: | |
- name: Notify no CVEs in Slack | |
if: success() | |
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 | |
env: | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
with: | |
channel-id: 'C05NM8419JM' # sda-dropwizard-commons-security | |
payload: | | |
{ | |
"blocks": [ | |
{ | |
"type": "header", | |
"text": { | |
"type": "plain_text", | |
"text": "${{ github.event.repository.name }}", | |
"emoji": true | |
} | |
}, | |
{ | |
"type": "context", | |
"elements": [ | |
{ | |
"type": "mrkdwn", | |
"text": ":large_green_circle: No CVEs found!" | |
} | |
] | |
} | |
] | |
} |