Validate gradle-wrapper.jar in CI against Gradle's published checksums, and pin the Gradle distribution with distributionSha256Sum. The wrapper JAR is a checked in binary that executes on developer laptops and build servers, so a pull request that swaps it deserves the same suspicion as any unreviewed executable.
Why the wrapper is an attack surface
Gradle's own documentation states the risk. The Wrapper JAR is a binary file executed on developer computers and build servers. Because it is usually committed to version control, a malicious actor could replace it with a modified one in a pull request that appears to only upgrade the Gradle version.
Code reviewers rarely open a binary diff. That is exactly why automation has to do it.
Step 1: validate the JAR automatically
If you build on GitHub, the Setup Gradle action validates the Wrapper JAR on every build. The documentation says that as of version 4 the validation is built in, with no separate action needed.
On other CI systems, run the manual check described next as a pipeline step.
Step 2: check the checksum yourself
Gradle publishes checksums for all releases except versions 3.3 to 4.0.2, which did not generate reproducible JARs. The documented Linux flow downloads the sha256 file for your Gradle version and runs a check against gradle/wrapper/gradle-wrapper.jar.
cd gradle/wrapper
curl --location --output gradle-wrapper.jar.sha256 \
https://services.gradle.org/distributions/gradle-9.8.1-wrapper.jar.sha256
echo " gradle-wrapper.jar" >> gradle-wrapper.jar.sha256
sha256sum --check gradle-wrapper.jar.sha256
Replace the version in the URL with the one your project uses. A result of OK means it matches. Anything else, stop the pipeline.
Step 3: pin the distribution checksum
The wrapper also downloads the Gradle distribution. Gradle lets you verify that download by adding the SHA-256 hash to gradle-wrapper.properties:
distributionSha256Sum=<hash from the published sha256 file>
Gradle fails the build if the checksum does not match the file on the hosting server. One caveat from the documentation: the check only runs if that distribution has not already been downloaded, so it matters most on clean CI agents and fresh clones.
Step 4: make the check a required gate
A check nobody enforces is a suggestion. Make wrapper validation a required status on pull requests that touch the gradle/wrapper directory, and require a code owner review for those paths.
| Control | Catches | Where it runs |
|---|---|---|
| Wrapper JAR validation | Modified wrapper binary | CI, on pull request |
| distributionSha256Sum | Tampered Gradle download | Every fresh build |
| Code owner on gradle/wrapper | Unreviewed wrapper changes | Review time |
Try it yourself
Click through it at your own pace, or open it full screen. See how a failing check blocks a merge until someone deals with it, which is the behavior you want for a changed wrapper file.
Safeguard policies and gates can block a pull request on dependency findings, and its dependency scanning covers the Gradle and Maven libraries your build resolves. Try a free scan at gold.safeguard.sh/scan.
Quick check
Is the wrapper JAR checked on every build by default?
No. Gradle does not validate it for you unless you add a check, such as the Setup Gradle action on GitHub or a manual checksum step.
Do I need both the JAR check and distributionSha256Sum?
They protect different files. One covers the small bootstrap binary in your repo, the other covers the Gradle distribution it downloads.
Sources
Last reviewed: 19 October 2026.