Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,90 @@ jobs:
PACKAGE_VERSION: ${{ github.event.release.tag_name }}
run: ./gradlew build

dependency-check:

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write

steps:
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
cache: gradle

- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Get cache week
id: date
run: echo "week=$(date -u +%Y-W%U)" >> "$GITHUB_OUTPUT"

- name: Cache dependency-check NVD data
uses: actions/cache@v4
with:
path: ~/.gradle/dependency-check-data
key: dependency-check-data-${{ steps.date.outputs.week }}
restore-keys: dependency-check-data-

- name: Run OWASP dependency-check
id: analyze
continue-on-error: true
env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
run: ./gradlew dependencyCheckAnalyze

- name: Upload dependency-check report
if: always()
uses: actions/upload-artifact@v4
with:
name: dependency-check-report
path: build/reports/dependency-check-report.html

- name: Build Markdown summary
if: always()
run: |
REPORT=build/reports/dependency-check-report.json
# Prefer NPM/GHSA scoring over NVD for npm deps, NVD often over-scores JS-ecosystem CVEs.
FINDINGS='
def score: (.cvssv3.baseScore // .cvssv2.score // 0);
def relevant($d): ($d.vulnerabilities | any(.source == "NPM"));
[ .dependencies[]? | select(.vulnerabilities != null) as $d
| $d.vulnerabilities[]
| select(if (relevant($d)) then .source == "NPM" else true end)
| select(score >= 7)
| {fileName: $d.fileName, name, severity: (.severity // "n/a"), cvss: score, source: (.source // "n/a")}
]
'
{
echo "### OWASP Dependency-Check results"
echo
echo "_Showing HIGH/CRITICAL findings (CVSS >= 7), GHSA-preferred over NVD for npm deps. Full report in the workflow artifact._"
echo
COUNT=$(jq "$FINDINGS | length" "$REPORT")
if [ "$COUNT" -eq 0 ]; then
echo "No HIGH/CRITICAL vulnerabilities found."
else
echo "| Dependency | CVE | Severity | CVSS | Source |"
echo "|---|---|---|---|---|"
jq -r "$FINDINGS"' | .[] | "| \(.fileName) | \(.name) | \(.severity) | \(.cvss) | \(.source) |"' "$REPORT"
fi
} > dependency-check-summary.md

- name: Comment PR with results
if: always() && github.event_name == 'pull_request'
uses: marocchino/sticky-pull-request-comment@v2
with:
header: dependency-check
path: dependency-check-summary.md

- name: Fail on vulnerabilities above threshold
if: steps.analyze.outcome == 'failure'
run: exit 1

release:
if: ${{ github.event_name == 'release' }}
runs-on: ubuntu-latest
Expand Down
11 changes: 11 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ plugins {
alias(libs.plugins.kover)
alias(libs.plugins.maven.publish)
alias(libs.plugins.sqldelight)
alias(libs.plugins.owasp.dependencycheck)
id("signing")
}

Expand Down Expand Up @@ -211,3 +212,13 @@ detekt {
html.required.set(true) // observe findings in your browser with structure and code snippets
}
}

dependencyCheck {
failBuildOnCVSS = 7.0f // fail on high/critical CVEs, don't block on low/medium noise
formats = listOf("HTML", "JSON") // JSON used to build the PR comment summary
suppressionFile = "$projectDir/gradle/dependency-check/suppression.xml"
scanSet.setFrom(file("$projectDir/kotlin-js-store/yarn.lock")) // npm sqlite3 dependency lockfile
nvd {
apiKey = System.getenv("NVD_API_KEY") ?: localProperties["nvd.apiKey"] as String?
}
}
5 changes: 5 additions & 0 deletions gradle/dependency-check/suppression.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
<!-- add <suppress> entries here for confirmed false positives, see
https://dependency-check.github.io/DependencyCheck/general/suppression.html -->
</suppressions>
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ kover = "0.9.9"
node-sqlite3 = "6.0.1"
node-js = "24.18.1"
maven-publish = "0.37.0"
owasp-dependencycheck = "12.2.2"
sqldelight = "2.3.2"

[libraries]
Expand All @@ -22,3 +23,4 @@ kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "maven-publish" }
owasp-dependencycheck = { id = "org.owasp.dependencycheck", version.ref = "owasp-dependencycheck" }
Loading