Skip to content

CVE Scanning

CVE Scanning #523

Workflow file for this run

name: CVE Scanning
on:
workflow_dispatch:
inputs:
scheduled:
description: 'Set by cve-scanning-schedule.yml when dispatching this run from the daily cron'
type: boolean
default: false
push:
branches:
- main
paths:
- 'pom.xml'
- 'CVE-suppressions.xml'
- '.github/workflows/cve-scanning.yml'
pull_request:
paths:
- 'pom.xml'
- 'CVE-suppressions.xml'
- '.github/workflows/cve-scanning.yml'
# Cancel previous jobs
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
depcheck:
# Fork PRs don't get repo secrets, so NVD_API_KEY would be empty and fail
# confusingly. Skip the job for fork PRs; other triggers (push, schedule,
# dispatch, same-repo PRs) are unaffected.
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Get current date
id: date
run: echo "date=$(date -u +'%Y-%m-%d')" >> "$GITHUB_OUTPUT"
# Persists the NVD dataset across runs, keyed by date, so runs resume
# instead of re-downloading. Split into restore/save (instead of the
# combined actions/cache action) because its save step only runs on job
# success, and the scan step below is expected to fail on a real CVSS>=7
# finding.
- name: Restore NVD data cache
id: nvd-cache-restore
uses: actions/cache/restore@v4
with:
path: .dependency-check-data
key: nvd-data-${{ steps.date.outputs.date }}
restore-keys: |
nvd-data-
# A partial download doesn't advance dependency-check's checkpoint, so a
# timed-out run just re-requests the same delta (upstream
# dependency-check#7180). A separate step with a large timeout lets the
# update eventually complete without blocking the scan below.
- name: Update NVD data
id: nvd-update
timeout-minutes: 300 # stay under the 360-minute GitHub-hosted runner job cap
continue-on-error: true
env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
run: |
mvn -B org.owasp:dependency-check-maven:12.2.2:update-only \
-DdataDirectory="${PWD}/.dependency-check-data" \
-DnvdApiKeyEnvironmentVariable=NVD_API_KEY \
-DnvdApiDelay=6000 \
-DnvdMaxRetryCount=30 \
-DnvdApiResultsPerPage=1000
# Saved right after the update, before the scan, so data is kept even
# if scanning fails. always() also covers the update step timing out,
# since partial data is still worth keeping.
- name: Save NVD data cache
if: always()
uses: actions/cache/save@v4
with:
path: .dependency-check-data
key: nvd-data-${{ steps.date.outputs.date }}
# Scans against whatever NVD data is already cached (autoUpdate=false),
# so this step stays fast and isn't blocked by a flaky/slow sync.
- name: CVE scanning
id: cve-scanning
run: |
mvn -B org.owasp:dependency-check-maven:12.2.2:aggregate \
-Dname="Rune Testing" \
-DdataDirectory="${PWD}/.dependency-check-data" \
-DautoUpdate=false \
-DsuppressionFiles=CVE-suppressions.xml \
-Dformats=HTML \
-DoutputDirectory=reports \
-DfailBuildOnCVSS=7 \
-DossIndexAnalyzerEnabled=true \
-DossIndexUsername=${{ secrets.OSSINDEX_USERNAME }} \
-DossIndexPassword=${{ secrets.OSSINDEX_TOKEN }} \
-DnodeAuditAnalyzerEnabled=false
- name: Upload results
if: always()
uses: actions/upload-artifact@v7
with:
name: CVE Scan Report
path: reports
- name: Note if the NVD update did not complete
if: steps.nvd-update.outcome == 'failure'
run: |
echo "::warning::The 'Update NVD data' step did not complete (see its log for details)."
if [ "${{ steps.cve-scanning.outcome }}" = "failure" ]; then
echo "::warning::The scan step also failed - if that failure is a NoDataException there is no cached NVD data yet (e.g. first ever run); otherwise it is likely a real CVSS>=7 finding, see the report artifact."
else
echo "::warning::The scan step still succeeded, using the last previously cached NVD data - it may be a few days stale until an update fully completes."
fi
# Notify Slack if the scan itself failed (e.g. a real CVSS>=7 finding),
# so the team doesn't have to check the Actions tab. Restricted to runs
# dispatched by cve-scanning-schedule.yml's daily cron so manual/PR/push
# triggers don't spam the channel.
- name: Notify Slack on scan failure
if: failure() && steps.cve-scanning.outcome == 'failure' && inputs.scheduled == true
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_GITHUB_WEBHOOK_URL }}
run: |
curl -sf -X POST -H 'Content-type: application/json' \
--data "{
\"text\": \":rotating_light: *CVE Scanning* failed for \`${{ github.repository }}\` on \`${{ github.head_ref || github.ref_name }}\` (triggered by \`${{ github.event_name }}\`).\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>\"
}" \
"$SLACK_WEBHOOK_URL"
# Also notify Slack on success for the scheduled run, so the team has
# positive confirmation that the daily scan is running and clean.
- name: Notify Slack on scan success
if: success() && inputs.scheduled == true
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_GITHUB_WEBHOOK_URL }}
run: |
curl -sf -X POST -H 'Content-type: application/json' \
--data "{
\"text\": \":white_check_mark: *CVE Scanning* passed for \`${{ github.repository }}\` on \`${{ github.head_ref || github.ref_name }}\`.\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>\"
}" \
"$SLACK_WEBHOOK_URL"