How to Secure JitPack Dependencies in build.gradle Against Supply Chain Attacks
Problem
When I scan my Android project’s dependencies, I find several JitPack dependencies that could be hijacked:
./gradlew dependencies --configuration releaseRuntimeClasspathI see output like this:
+--- com.github.abandoned-user:library:1.0.0| +--- com.github.transitive:lib:2.1.0The problem is that these dependencies come from JitPack with mutable version tags like @main or @latest, which means anyone could hijack the abandoned namespace and publish malicious code.
Environment
- Gradle 8.0
- Android Gradle Plugin 8.1.0
- Java 17
- JitPack dependencies in build.gradle
What happened?
I read about a security researcher’s findings on JitPack supply chain vulnerabilities. They explained that JitPack allows anyone to publish packages to any namespace. If a GitHub user abandons their account or deletes their repo, a malicious actor can claim the same namespace and publish malicious versions with the same dependency coordinates.
Here’s my vulnerable build.gradle:
dependencies { // Vulnerable: tag can be hijacked implementation 'com.github.user:repo:latest'
// Vulnerable: branch can be changed by anyone implementation 'com.github.user:repo:main-SNAPSHOT'
// Vulnerable: even specific tags can be republished implementation 'com.github.abandoned-user:library:1.0.0'}The issue is that com.github.user:repo:latest doesn’t pin to anything immutable. If the user account is abandoned, someone else could claim it and push a new “latest” version that contains malware.
How to solve it?
I tried three approaches to secure my JitPack dependencies.
Step 1: Pin dependencies to commit hashes
I replaced mutable version tags with specific commit hashes:
dependencies { // Secure: pinned to specific commit hash implementation 'com.github.user:repo:1.2.3'
// Find the commit hash from GitHub releases or tags // Example: commit abc123def becomes version abc123def}But this alone isn’t enough. I need to verify the artifact checksums.
Step 2: Enable Gradle dependency verification
I added verification metadata to my project. First, I generated the metadata file:
./gradlew --write-verification-metadata sha512This created a verification-metadata.xml file in my project root:
<?xml version="1.1" encoding="UTF-8"?><verification-metadata xmlns="https://schema.gradle.org/dependency-verification" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://schema.gradle.org/dependency-verification https://schema.gradle.org/dependency-verification/dependency-verification-1.3.xsd"> <configuration> <verify-metadata>true</verify-metadata> <verify-signatures>false</verify-signatures> <trusted-artifacts> <trust group="com.github.user" name="repo" version="1.2.3" reason="Pinned commit"/> </trusted-artifacts> </configuration> <components> <component group="com.github.user" name="repo" version="1.2.3"> <artifact name="repo-1.2.3.jar"> <sha512 value="a1b2c3d4e5f67890abcdef1234567890..." algorithm="SHA-512"/> </artifact> </component> </components></verification-metadata>Then I enabled it in my settings.gradle:
dependencyResolutionManagement { verificationMode = VerificationMode.STRICT}Now when I build, Gradle verifies the checksums. If someone hijacks the namespace and publishes a malicious artifact, the build fails because the SHA-512 hash doesn’t match.
Step 3: Scan transitive dependencies
I needed to check all dependencies, not just the ones I directly include:
./gradlew dependencies --configuration releaseRuntimeClasspathI found transitive dependencies also using JitPack:
+--- com.github.direct:lib:1.0.0| \--- com.github.transitive:core:2.0.0 <-- Transitive JitPack dep!For these, I used dependencyInsight to see where they come from:
./gradlew dependencyInsight --dependency com.github.transitive:core --configuration releaseRuntimeClasspathOutput showed which direct dependency pulls it in:
com.github.transitive:core:2.0.0 +--- com.github.direct:lib:1.0.0| \--- project :appNow I can either:
- Exclude the transitive dependency
- Pin it directly with checksum verification
- Contact the upstream maintainer to use a secure repository
Testing the fix
I tested the verification by modifying a checksum in verification-metadata.xml:
<sha512 value="0000000000000000..." algorithm="SHA-512"/>Then I ran the build:
./gradlew buildThe build failed with:
Execution failed for task ':app:checkDebugAndroidTestDuplicateClasses'.> Could not resolve com.github.user:repo:1.2.3. > Artifact verification failed for com.github.user:repo:1.2.3This confirms the verification is working. I reverted the checksum and the build succeeded.
The reason
The key reason for this vulnerability is that JitPack doesn’t enforce namespace ownership. Unlike Maven Central, where publishing requires signing keys and ownership verification, JitPack constructs the group ID from the GitHub username com.github.{username}. If the username is abandoned, anyone can claim it.
By pinning to commit hashes and enabling checksum verification, I create two layers of defense:
- The commit hash ensures I’m getting a specific version from a specific commit
- The checksum ensures the artifact content hasn’t been tampered with
This is the same defense-in-depth principle used in npm package-lock.json, Rust’s Cargo.lock, and Python’s pip requirements with hashes.
Summary
In this post, I showed how to secure JitPack dependencies against supply chain attacks by pinning to commit hashes, enabling Gradle verification metadata, and scanning transitive dependencies. The key point is that mutable version tags like latest or main-SNAPSHOT are vulnerable to namespace hijacking, and you need checksum verification to ensure artifact integrity.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 JitPack Supply Chain Vulnerability Discussion
- 👨💻 Gradle Dependency Verification Documentation
- 👨💻 OWASP Supply Chain Security
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments