Symptom

Nightly dependency-CVE scan (Kraken) flagged org.apache.commons:commons-lang3 with GHSA-j288-q9x7-2f5v (severity: medium; affected range >= 3.0, < 3.18.0). No explicit version was pinned, leaving the version solely in transitive conflict-resolution hands.

Root cause

commons-lang3 was not listed in gradle/libs.versions.toml and no resolutionStrategy floor was applied. Gradle’s conflict-resolution happened to select 3.18.0 (via commons-compress:1.28.0 → dataframe-arrow / POI / kandy), but nothing prevented a future transitive update from introducing a vulnerable sub-3.18.0 version undetected.

Fix

Prevention

When a transitive CVE is cleared by Gradle’s existing conflict-resolution (i.e., the resolved version already satisfies the floor), still add an explicit resolutionStrategy floor so any future transitive regression is caught at build time, not discovered by the next CVE scan.

Note on Gradle accessor naming: multi-segment version catalog keys (e.g., commons-lang3) generate NESTED type-safe accessors (libs.versions.commons.lang3), while single-segment keys (e.g., log4j2, gson) generate flat accessors (libs.versions.log4j2). Attempting libs.versions.commonsLang3 (flat camelCase) for a two-segment key is an unresolved reference.