Skip to content

Commit 0d61665

Browse files
committed
Add a check for CVEs present in new transitive dependencies
This action will compare the baseline and PR's CVE count, and fail if new high or critical CVEs are present in the PR.
1 parent de0fe1c commit 0d61665

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
name: Maven OWASP Dependency Check
2+
on:
3+
pull_request:
4+
workflow_dispatch:
5+
inputs:
6+
cvss-threshold:
7+
description: 'CVSS score threshold for failing (7.0 = high/critical)'
8+
required: false
9+
default: '7.0'
10+
type: string
11+
12+
jobs:
13+
dependency-check:
14+
runs-on: ubuntu-latest
15+
env:
16+
CVSS_THRESHOLD: ${{ github.event.inputs.cvss-threshold || '7.0' }}
17+
OWASP_VERSION: '12.1.3'
18+
steps:
19+
- name: Checkout PR branch
20+
uses: actions/checkout@v4
21+
with:
22+
ref: ${{ github.event.pull_request.head.sha }}
23+
path: pr
24+
25+
- name: Checkout base branch
26+
uses: actions/checkout@v4
27+
with:
28+
ref: ${{ github.event.pull_request.base.sha }}
29+
path: base
30+
31+
- name: Set up Java
32+
uses: actions/setup-java@v4
33+
with:
34+
distribution: 'temurin'
35+
java-version: 17
36+
cache: 'maven'
37+
38+
- name: Get date for cache key
39+
id: get-date
40+
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
41+
42+
- name: Restore OWASP database cache
43+
uses: actions/cache/restore@v4
44+
id: cache-owasp-restore
45+
with:
46+
path: ~/.owasp/dependency-check-data
47+
key: owasp-cache-${{ runner.os }}-${{ env.OWASP_VERSION }}-${{ steps.get-date.outputs.date }}
48+
restore-keys: |
49+
owasp-cache-${{ runner.os }}-${{ env.OWASP_VERSION }}-
50+
owasp-cache-${{ runner.os }}-
51+
52+
- name: Run OWASP check on base branch
53+
working-directory: base
54+
run: |
55+
mvn org.owasp:dependency-check-maven:${{ env.OWASP_VERSION }}:aggregate \
56+
-DskipTests \
57+
-Dformat=JSON \
58+
-DprettyPrint=true \
59+
-DfailOnError=false \
60+
-DossindexAnalyzerEnabled=true \
61+
-DnvdApiAnalyzerEnabled=false \
62+
-DnodeAnalyzerEnabled=false \
63+
-DassemblyAnalyzerEnabled=false \
64+
-DcentralAnalyzerEnabled=false \
65+
-DnuspecAnalyzerEnabled=false \
66+
-DnvdValidForHours=168 \
67+
-DdataDirectory=$HOME/.owasp/dependency-check-data
68+
69+
- name: Save OWASP cache after base scan
70+
if: steps.cache-owasp-restore.outputs.cache-hit != 'true'
71+
uses: actions/cache/save@v4
72+
with:
73+
path: ~/.owasp/dependency-check-data
74+
key: owasp-cache-${{ runner.os }}-${{ env.OWASP_VERSION }}-${{ steps.get-date.outputs.date }}-partial
75+
76+
- name: Run OWASP check on PR branch
77+
working-directory: pr
78+
run: |
79+
mvn org.owasp:dependency-check-maven:${{ env.OWASP_VERSION }}:aggregate \
80+
-DskipTests \
81+
-Dformat=JSON \
82+
-DprettyPrint=true \
83+
-DfailOnError=false \
84+
-DossindexAnalyzerEnabled=true \
85+
-DnvdApiAnalyzerEnabled=false \
86+
-DnodeAnalyzerEnabled=false \
87+
-DassemblyAnalyzerEnabled=false \
88+
-DcentralAnalyzerEnabled=false \
89+
-DnuspecAnalyzerEnabled=false \
90+
-DnvdValidForHours=168 \
91+
-DdataDirectory=$HOME/.owasp/dependency-check-data
92+
93+
- name: Compare and fail on new CVEs above threshold
94+
run: |
95+
# Extract CVEs above threshold from both branches (CVSS >= $CVSS_THRESHOLD)
96+
threshold="${{ env.CVSS_THRESHOLD }}"
97+
base_cves=$(cat base/target/dependency-check-report.json 2>/dev/null | jq -r ".dependencies[].vulnerabilities[]? | select((.cvssv2.score // 0) >= $threshold or (.cvssv3.baseScore // 0) >= $threshold) | .name" | grep -E '^CVE-[0-9]{4}-[0-9]+$' | sort -u)
98+
pr_cves=$(cat pr/target/dependency-check-report.json 2>/dev/null | jq -r ".dependencies[].vulnerabilities[]? | select((.cvssv2.score // 0) >= $threshold or (.cvssv3.baseScore // 0) >= $threshold) | .name" | grep -E '^CVE-[0-9]{4}-[0-9]+$' | sort -u)
99+
100+
# Find new CVEs introduced in PR
101+
new_cves=$(comm -13 <(echo "$base_cves") <(echo "$pr_cves"))
102+
103+
if [ -n "$new_cves" ]; then
104+
echo "❌ New vulnerabilities introduced in PR:"
105+
echo "$new_cves"
106+
echo ""
107+
108+
for cve in $new_cves; do
109+
echo "=================================================="
110+
echo "CVE: $cve"
111+
echo "=================================================="
112+
113+
# Find which dependencies have this CVE
114+
cat pr/target/dependency-check-report.json | jq -r ".dependencies[] | select(.vulnerabilities[]?.name == \"$cve\") | \"Module: \" + (.projectReferences // [\"root\"])[0] + \"\nDependency: \" + .fileName + \"\nPackage: \" + (if .packages and .packages[0] then .packages[0].id else \"N/A\" end) + \"\nDescription: \" + (.vulnerabilities[] | select(.name == \"$cve\") | .description)"
115+
116+
echo ""
117+
done
118+
119+
exit 1
120+
else
121+
echo "✅ No new vulnerabilities introduced"
122+
fi
123+
124+
- name: Save OWASP database cache
125+
if: always()
126+
uses: actions/cache/save@v4
127+
with:
128+
path: ~/.owasp/dependency-check-data
129+
key: owasp-cache-${{ runner.os }}-${{ env.OWASP_VERSION }}-${{ steps.get-date.outputs.date }}
130+
131+
- name: Upload reports
132+
if: always()
133+
uses: actions/upload-artifact@v4
134+
with:
135+
name: owasp-reports
136+
path: |
137+
base/target/dependency-check-report.json
138+
pr/target/dependency-check-report.json

0 commit comments

Comments
 (0)