diff --git a/config/owasp/dependency-check-suppressions.xml b/config/owasp/dependency-check-suppressions.xml new file mode 100644 index 0000000000..e18f37edb1 --- /dev/null +++ b/config/owasp/dependency-check-suppressions.xml @@ -0,0 +1,259 @@ + + + + + + + + ^pkg:maven/androidx\.browser/browser@.*$ + cpe:/a:android:android_browser + + + + + + ^pkg:maven/com\.microsoft\.identity/common4j@.*$ + cpe:/a:microsoft:authentication_library + + + + ^pkg:maven/com\.microsoft\.identity/common@.*$ + cpe:/a:microsoft:authentication_library + + + + + + ^pkg:maven/org\.jetbrains\.kotlin/kotlin-stdlib@.*$ + CVE-2020-29582 + + + + ^pkg:maven/org\.jetbrains\.kotlin/kotlin-stdlib-jdk7@.*$ + CVE-2020-29582 + + + + ^pkg:maven/org\.jetbrains\.kotlin/kotlin-stdlib-jdk8@.*$ + CVE-2020-29582 + + + + + + ^pkg:maven/io\.opentelemetry/opentelemetry-api@.*$ + cpe:/a:opentelemetry:opentelemetry + + + + ^pkg:maven/io\.opentelemetry/opentelemetry-context@.*$ + cpe:/a:opentelemetry:opentelemetry + + + + ^pkg:maven/io\.opentelemetry/opentelemetry-extension-kotlin@.*$ + cpe:/a:opentelemetry:opentelemetry + + + + + + ^pkg:maven/com\.google\.protobuf/protobuf-javalite@.*$ + CVE-2021-22569 + + + + + + ^pkg:maven/com\.google\.protobuf/protobuf-javalite@.*$ + CVE-2022-3171 + + + + ^pkg:maven/com\.google\.protobuf/protobuf-javalite@.*$ + CVE-2024-7254 + + + diff --git a/msal/build.gradle b/msal/build.gradle index 8efffa5079..fc5e96c89c 100644 --- a/msal/build.gradle +++ b/msal/build.gradle @@ -9,6 +9,7 @@ plugins { // Test retries id 'org.gradle.test-retry' version '1.5.6' + id 'org.owasp.dependencycheck' version '12.2.2' } apply from: 'versioning/version_tasks.gradle' @@ -444,3 +445,74 @@ tasks.whenTaskAdded { task -> tasks.withType(GenerateMavenPom).all { destination = layout.buildDirectory.file("poms/${project.name}-${project.version}.pom").get().asFile } + +// --------------------------------------------------------------------------- +// OWASP Dependency-Check (plugin applied in `plugins { }` at top of file) +// --------------------------------------------------------------------------- +// Wires `dependencyCheckAnalyze` into `check` and configures the NVD scanner +// for an Android library. Tunables (override on CLI): +// -PdependencyCheckFailOnCvss=11 (default 7.0; use 11 to never fail the build) +// -PdependencyCheckFormats=HTML,JSON,SARIF +// +// NVD API key — required, no hardcoded fallback (this file ships in a public repo). +// Resolution order (first wins): -PnvdApiKey → gradle.properties: nvdApiKey → env NVD_API_KEY +// Missing key triggers fail-fast in the taskGraph hook below (avoids confusing +// 429 / NoDataException cascade from inside the plugin). +def dependencyCheckAutoUpdate = (project.findProperty("dependencyCheckAutoUpdate") ?: "false").toBoolean() +def dependencyCheckFailOnCvss = (project.findProperty("dependencyCheckFailOnCvss") ?: "7.0").toFloat() +def dependencyCheckFormats = (project.findProperty("dependencyCheckFormats")?.toString()?.split(",")*.trim() + ?: ["HTML", "JSON"]) +def dependencyCheckSuppressionFile = file("${projectDir}/../config/owasp/dependency-check-suppressions.xml") +def __nvdApiKey = (project.findProperty("nvdApiKey") ?: System.getenv("NVD_API_KEY"))?.toString()?.trim() + +dependencyCheck { + autoUpdate = dependencyCheckAutoUpdate + failBuildOnCVSS = dependencyCheckFailOnCvss + formats = dependencyCheckFormats + outputDirectory = layout.buildDirectory.dir("reports/dependency-check").get().asFile.absolutePath + + // NOTE on API shape: dependency-check-gradle 12.x @Deprecated the closure forms + // `nvd { ... }` and `analyzers { ... }`. Use flat `nvd.` / `analyzers.`. + // `cve.validForHours` / `cveValidForHours` are NOT exposed in 12.x — caching is + // handled internally by the plugin's H2 DB at ~/.gradle/dependency-check-data/. + if (__nvdApiKey) { + nvd.apiKey = __nvdApiKey + } + nvd.delay = 2000 // ms between calls; keyed throughput is ~50 req/30s + nvd.maxRetryCount = 10 + + // Only scan shipped runtime classpaths (skip test/androidTest for speed + signal). + scanConfigurations = [ + "distReleaseRuntimeClasspath", "distDebugRuntimeClasspath", + "localReleaseRuntimeClasspath", "localDebugRuntimeClasspath" + ] + + if (dependencyCheckSuppressionFile.exists()) { + suppressionFile = dependencyCheckSuppressionFile.absolutePath + } + + // Disabled analyzers — not relevant for an Android/Java library: + analyzers.assemblyEnabled = false // .NET assemblies + analyzers.nuspecEnabled = false // NuGet + analyzers.nodePackage.enabled = false // npm + analyzers.nodeAudit.enabled = false // npm audit + analyzers.ossIndex.enabled = false // requires Sonatype Guide token + + // ArchiveAnalyzer disabled: crashes with NoSuchMethodError on ZipFile.builder() + // because AGP's buildscript classpath shadows commons-compress < 1.26 into the + // plugin classloader. Maven GAV-based detection (JarAnalyzer) still covers all + // our AARs, so we lose no CVE coverage. + analyzers.archiveEnabled = false +} + +tasks.named('check').configure { dependsOn 'dependencyCheckAnalyze' } + +// Fail fast on missing NVD key only when the scan is actually in the task graph, +// so IDE sync / `./gradlew tasks` aren't broken. +gradle.taskGraph.whenReady { graph -> + if (!__nvdApiKey && graph.hasTask(project.tasks.named('dependencyCheckAnalyze').get())) { + throw new GradleException( + "OWASP dependency-check requires an NVD API key.\n" + + "Provide via: -PnvdApiKey= | gradle.properties: nvdApiKey= | env NVD_API_KEY=") + } +}