Skip to main content
The Root.io Gradle Plugin intercepts dependency resolution and transparently substitutes vulnerable dependencies with Root-patched versions from pkg.root.io/maven/. You declare the versions you know, and the plugin handles the rest—no changes to your dependency declarations required.

Root.io Gradle Plugin

View the source code, report issues, or contribute to the Root.io Gradle Plugin.

Prerequisites

Installation

Add the Root.io Gradle Plugin repository to settings.gradle.kts:
pluginManagement {
    repositories {
        maven {
            url = uri("https://pkg.root.io/gradle-plugins")
            credentials {
                username = "token"
                password = providers.environmentVariable("ROOTIO_API_KEY").get()
            }
        }
        gradlePluginPortal()
    }
}
Apply the plugin in build.gradle.kts:
plugins {
    id("io.root.patcher") version "0.1.0"
}

Option 2: Local Maven Repository

For testing or air-gapped environments:
cd rootio_gradle_plugin/
make publish-local
Then add mavenLocal() to your pluginManagement repositories:
pluginManagement {
    repositories {
        mavenLocal()
        gradlePluginPortal()
    }
}

How It Works

When you run a build, the plugin will:
  1. Query Root.io API for patches on your declared dependencies
  2. Substitute patched versions if available
  3. Register pkg.root.io/maven/ as a Maven repository
  4. Cache results locally at .gradle/rootio-cache/

Configuration

Configure the plugin in build.gradle.kts:
rootio {
    apiKey.set("your-api-key-here")  // Optional if using env vars
    apiUrl.set("https://api.root.io")  // Default
    pkgUrl.set("https://pkg.root.io")  // Default
    ttlHours.set(24)  // Cache TTL (0 = no cache)
    maxRetries.set(3)  // Max retry attempts
    retryBaseDelayMs.set(1000)  // Exponential backoff base
    allowInsecurePkgRepo.set(false)  // Allow HTTP (test only)
}

Configuration Properties

PropertyDefaultDescription
apiKeyRoot.io API key (see API Key Resolution)
apiUrlhttps://api.root.ioRoot.io API base URL
pkgUrlhttps://pkg.root.ioRoot.io package registry base URL
ttlHours24Cache TTL in hours (0 disables caching)
maxRetries3Max retry attempts for transient API failures
retryBaseDelayMs1000Base delay (ms) for exponential backoff
allowInsecurePkgRepofalseAllow plain HTTP for package repo (test/local only)

API Key Resolution

The plugin resolves the API key in this order (highest priority first):
  1. Build script: rootio { apiKey.set("...") }
  2. Environment variable: export ROOTIO_API_KEY=...
  3. JVM system property: systemProp.ROOTIO_API_KEY=... in ~/.gradle/gradle.properties
  4. .env file: ROOTIO_API_KEY=... in project root
Keep your API key out of source control. Use environment variables or JVM system properties for CI/CD.

Multi-Project Setup

Apply the plugin once at the root and propagate to all subprojects:
// settings.gradle.kts
pluginManagement {
    repositories {
        maven {
            url = uri("https://pkg.root.io/gradle-plugins")
            credentials {
                username = "token"
                password = providers.environmentVariable("ROOTIO_API_KEY").get()
            }
        }
        gradlePluginPortal()
    }
}

// Root build.gradle.kts
plugins {
    id("io.root.patcher") version "0.1.0" apply false
}

subprojects {
    apply(plugin = "io.root.patcher")

    repositories {
        mavenCentral()
    }
}

// app/build.gradle.kts
dependencies {
    implementation("io.netty:netty-all:4.1.42.Final")
}

// lib/build.gradle.kts
dependencies {
    implementation("commons-beanutils:commons-beanutils:1.9.3")
}
Run the build:
export ROOTIO_API_KEY="your-api-key-here"
./gradlew build
All subprojects will automatically use Root-patched dependencies.

Caching

The plugin caches Root.io API responses locally at .gradle/rootio-cache/ to avoid repeated network calls. The cache is not used when:
  • The cached response is older than the TTL (default: 24 hours)
  • ttlHours.set(0) is configured (caching disabled)
  • A dependency is queried for the first time
  • The cache directory has been manually cleared
To clear the cache:
rm -rf .gradle/rootio-cache/

Detailed Flow

  1. Plugin applies to your project and creates the rootio {} configuration extension
  2. API key resolution happens in priority order (build script → env var → system property → .env)
  3. Root.io Maven repository is registered automatically with credentials
  4. Resolution hooks are installed on every resolvable configuration
  5. For each dependency, the plugin:
    • Checks the local cache (.gradle/rootio-cache/) for a valid entry
    • If cache miss, queries Root.io API (/v3/analyze/maven) for patches
    • Substitutes the dependency coordinates if a patch is available
    • Logs the patching decision
  6. Gradle resolves the patched version from pkg.root.io/maven/

Troubleshooting

IssueSolution
401 Unauthorized from Root.io APIVerify ROOTIO_API_KEY is set correctly (see API Key Resolution)
404 Not Found for patched artifactConfirm the patched version exists in pkg.root.io/maven/ (check Root.io dashboard)
Plugin not applying patchesCheck Gradle console output for [Root.io] log messages. Ensure plugin is applied before dependencies are declared.
Network timeoutsIncrease retryBaseDelayMs and maxRetries in the rootio {} block
Cache is staleDelete .gradle/rootio-cache/ or set ttlHours.set(0) to disable caching
ResolutionStrategy conflictsRoot.io plugin uses eachDependency hooks. Ensure no other plugins conflict with dependency resolution.
Multi-project builds not patching subprojectsVerify apply(plugin = "io.root.patcher") is in the subprojects {} block
If you encounter issues, check the Gradle build output for [Root.io] prefixed log messages. Run with --info or --debug for detailed output: ./gradlew build --info