Skip to content

Search

Search the docs, blog, and marketplace.

gradle

Last updated October 25, 2026View source (v0.30.0)

This page explains how Bomly builds a dependency graph for gradle projects: the detector chain it runs, what that chain needs, and what it can report.

PropertyValue
Package managergradle
Ecosystemmaven
Detector chaingradle-detector, syft-detector
Evidence patternsbuild.gradle, build.gradle.kts, settings.gradle, settings.gradle.kts, gradle.lockfile*
Ignored directoriesbuild
Multi-module resolutionYes
Install-first supportYes
Remediation hintsdirect-bump1, transitive-override2
Commands the chain may rungradle. The Syft fallback is built in; the lite build runs an external syft from PATH instead.

How gradle resolves

gradle-detector is a build-tool primary chain. Bomly runs Gradle's own resolver to produce the graph.

StepCommandWorking dir
Resolve graph./gradlew dependencies --console=plain (or gradle dependencies --console=plain without a wrapper)every directory containing build.gradle or build.gradle.kts

Bomly parses the output of the dependencies task into a transitive graph and keeps the configuration scopes.

gradle dependencies may download artifacts during a plain scan. Gradle fetches missing artifacts from the repositories your build files declare, usually mavenCentral() and google(). That is Gradle's behavior, not Bomly's, and the same downloads happen when you run ./gradlew build. A committed gradle.lockfile lets Gradle resolve offline once the cache is warm, but it does not prevent the first cold-cache fetch. See Network and privacy for the shared rule.

Prerequisites

  • gradle or ./gradlew (the Gradle wrapper) on PATH. Prefer the wrapper, because it pins the Gradle version your project expects.
  • A build.gradle or build.gradle.kts. Bomly treats every Gradle module under settings.gradle as a subproject.
  • For full lock detail: a committed gradle.lockfile. Enable it with dependencyLocking { lockAllConfigurations() } and run ./gradlew dependencies --write-locks.

Examples

Fix a direct vulnerability

Raise the version in build.gradle.kts:

implementation("com.fasterxml.jackson.core:jackson-databind:2.17.1")

Re-lock with ./gradlew dependencies --write-locks and re-scan.

Pin a transitive vulnerability

Use a resolution strategy in your root build.gradle.kts:

configurations.all {
  resolutionStrategy.eachDependency {
    if (requested.group == "com.fasterxml.jackson.core" &&
        requested.name  == "jackson-databind") {
      useVersion("2.17.1")
    }
  }
}

Re-lock and re-scan.

--install-first

With --install-first, Bomly runs the same gradle dependencies --console=plain command that drives normal resolution. Gradle fetches missing artifacts as a side effect, which warms the local cache. Use it on a clean checkout when the Gradle cache is cold:

bomly scan --install-first

To append flags to that command, repeat --install-arg. This requires --detectors gradle-detector:

# Refresh dependencies and target one configuration
bomly scan --install-first --detectors gradle-detector \
  --install-arg --refresh-dependencies \
  --install-arg --configuration --install-arg runtimeClasspath

Reachability (experimental)

With --analyze, the jvmreach analyzer reports a Gradle package as reachable when app source imports a class from it. For multi-project builds it reads include(...) declarations and projectDir overrides. Dynamically computed settings and includeBuild closures are best effort. Unreachable is a triage signal, not proof of safety; see Reachability.

Limitations

  • Gradle is required. There is no offline-only path for Gradle graph resolution.
  • Composite builds (includeBuild) are scanned per included build. Cross-build edges are best effort.
  • Dynamic versions (+, latest.release, version ranges) are resolved when you lock, not by Bomly. A stale gradle.lockfile does not pick up new advisories until you re-lock.
  • Annotation processors that generate code at build time are invisible to source-based reachability.
  • Kotlin Multiplatform target-specific dependencies are all included. Per-target reachability is not computed.

Footnotes

  1. Update a package declared directly in the project. ↩

  2. Pin an indirect package with the package manager's override feature. ↩