From 4ce3c719e2142cd2efa91b3634627464cf915ee0 Mon Sep 17 00:00:00 2001 From: Ned Wolpert Date: Sun, 19 Jul 2026 07:52:24 -0700 Subject: [PATCH] Floor vulnerable transitive dependencies (Dependabot alerts) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve the 17 open Dependabot security alerts, all of which are transitive dependencies (they cite settings.gradle.kts): Netty (via Lettuce), Jackson 2.x and logback (via Dropwizard), commons-compress (via Testcontainers), and rhino (via swagger-parser). Rather than pin exact versions, raise each to its first patched release as a *floor* via version-catalog-driven Gradle dependency constraints in velocity.java-conventions (inherited by every module): - platform(netty-bom) / platform(jackson2-bom) align each multi-artifact family so we never split e.g. netty-handler 4.2.15 against netty-buffer 4.2.13. - a constraints { } block floors the standalone coordinates (logback-core, logback-classic, commons-compress, commons-lang3, rhino). Floor (not pin) semantics mean a higher version reached by any other path still wins, so future upgrades are never blocked — proven live: commons-lang3 floors at 3.18.0 but still resolves to the higher transitive 3.20.0. All versions live in libs.versions.toml, so the existing weekly Dependabot gradle job bumps them forward automatically. No source or velocity-spi/velocity-api contract changes (NFR-17 unaffected). Verified: ./gradlew clean build test green incl. jacocoTestCoverageVerification; dependencyInsight confirms every flagged artifact resolves at/above its patched release. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../velocity.java-conventions.gradle.kts | 23 +++++++++++++++++++ gradle/libs.versions.toml | 22 ++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/build-logic/src/main/kotlin/velocity.java-conventions.gradle.kts b/build-logic/src/main/kotlin/velocity.java-conventions.gradle.kts index ac46453..bd49f44 100644 --- a/build-logic/src/main/kotlin/velocity.java-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/velocity.java-conventions.gradle.kts @@ -21,6 +21,29 @@ java { dependencies { compileOnly(libs.jspecify) errorprone(libs.build.errorprone.core) + + // --- Transitive security floors (Dependabot alerts) --------------------------------------- + // None of these are direct dependencies; they arrive transitively (Netty via Lettuce, + // Jackson 2.x + logback via Dropwizard, commons-compress via Testcontainers, rhino via + // swagger-parser). We raise each to its first patched release as a *floor*, not a pin: + // - `platform(...)` imports a BOM as constraints, aligning a whole artifact family (Netty's + // ~9 modules, Jackson 2.x's ~12) to one version so we never split e.g. netty-handler 4.2.15 + // against netty-buffer 4.2.13. + // - the `constraints { }` block floors the standalone coordinates. + // Floor semantics mean a higher version reached by any other path still wins, so these never + // block a future upgrade; Dependabot bumps the catalog entries on its weekly gradle run. + // Declared on `implementation` so they reach runtimeClasspath and (via testImplementation + // extendsFrom implementation) the test classpaths where rhino/commons-compress live. Modules + // that don't pull a given artifact are unaffected — an unused constraint is a no-op. + implementation(platform(libs.netty.bom)) + implementation(platform(libs.jackson2.bom)) + constraints { + implementation(libs.logback.core) { because("logback-core object-injection advisory") } + implementation(libs.logback.classic) { because("keep logback-classic aligned with logback-core floor") } + implementation(libs.commons.compress) { because("commons-compress Pack200/DUMP DoS advisories") } + implementation(libs.commons.lang3) { because("commons-lang3 uncontrolled-recursion advisory") } + implementation(libs.rhino) { because("rhino toFixed() DoS advisory") } + } } tasks.withType().configureEach { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 65bfa32..3d032a6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -58,6 +58,18 @@ assertj = "3.27.7" mockito = "5.23.0" logback = "1.5.38" +# Security floors for transitive dependencies (see the "Transitive security floors" block in +# velocity.java-conventions). None of these are direct dependencies of ours — they arrive +# transitively (Netty via Lettuce, Jackson 2.x/logback via Dropwizard, commons-compress via +# Testcontainers, rhino via swagger-parser). Each value is the first patched release for the +# corresponding Dependabot advisory; it is applied as a *floor*, not a pin, so a higher version +# on any resolution path still wins. Dependabot keeps these current on its weekly gradle run. +netty = "4.2.15.Final" # netty-handler / netty-resolver-dns advisories (GHSA, high) +jackson2 = "2.21.5" # jackson-databind 2.x case-insensitive @JsonIgnoreProperties bypass +commons-compress = "1.26.0" # Pack200 OOM + corrupted-DUMP infinite-loop DoS +commons-lang3 = "3.18.0" # uncontrolled recursion on long inputs +rhino = "1.7.14.1" # toFixed() high-CPU DoS + [libraries] jspecify = { module = "org.jspecify:jspecify", version.ref = "jspecify" } @@ -114,6 +126,16 @@ mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" } mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" } logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } +# Transitive security floors — referenced only by the constraints block in +# velocity.java-conventions, never depended on directly. BOMs (netty, jackson 2.x) align a whole +# artifact family to one version; the singletons floor one coordinate each. +netty-bom = { module = "io.netty:netty-bom", version.ref = "netty" } +jackson2-bom = { module = "com.fasterxml.jackson:jackson-bom", version.ref = "jackson2" } +logback-core = { module = "ch.qos.logback:logback-core", version.ref = "logback" } +commons-compress = { module = "org.apache.commons:commons-compress", version.ref = "commons-compress" } +commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commons-lang3" } +rhino = { module = "org.mozilla:rhino", version.ref = "rhino" } + [bundles] test = ["junit-jupiter", "assertj-core", "mockito-core", "mockito-junit-jupiter"] jackson = ["jackson-databind", "jackson-annotations"]