skip to content

Wrapper & Distribution

The wrapper files that pin a Gradle version per project, their properties, the regeneration task, and the integrity checks around the wrapper jar. Interviewers ask because the wrapper is both a reproducibility tool and a supply-chain surface.

on this pageshow

explore

questions

25

What is the distributionSha256Sum property in gradle-wrapper.properties, and what does it protect against?

level: juniorimportance: must knowfreq 45%

answer

  1. SHA-256 of the distribution ZIP
  2. line in gradle-wrapper.properties
  3. verified on download, fail-closed
  4. supply-chain / tampered mirror defense
  5. complements HTTPS, not replaces it

basics

~10 s

It's a SHA-256 checksum of the Gradle distribution ZIP, stored in gradle-wrapper.properties. The wrapper verifies the downloaded distribution against it and aborts if they don't match, protecting against a tampered or corrupted download.

solid answer

~40 s

`distributionSha256Sum` is an optional line in `gradle-wrapper.properties` holding the expected SHA-256 hash of the Gradle distribution archive named by `distributionUrl`. When the wrapper downloads that archive, it computes the SHA-256 of the bytes it received and compares it to this pinned value. On a mismatch the build fails before the distribution is unpacked or executed — so no untrusted Gradle code runs. This defends against a corrupted download, a compromised mirror/CDN, or a man-in-the-middle who swaps the ZIP. Without it, the wrapper trusts whatever the URL serves. It complements (but is separate from) verifying the wrapper JAR itself; this property is specifically about the downloaded *distribution* archive.

code

toml · 7 lines
toml
# gradle/wrapper/gradle-wrapper.properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

go deeper

for a junior

Know it's a SHA-256 of the Gradle distribution ZIP in gradle-wrapper.properties and that a mismatch fails the build.

for a middle

Explain it's verified at download time, fails closed before execution, and why it adds value beyond HTTPS.

for a senior

Frame it as supply-chain defense-in-depth, distinguish it from wrapper-JAR verification, and know where the official sum is published.

for a principal

Position it within a software-supply-chain policy: enforce pinning org-wide, fail closed, and treat the distribution as untrusted-until-verified code.

## What the wrapper does The Gradle Wrapper is a small script + JAR checked into your repo. On first use it reads `gradle/wrapper/gradle-wrapper.properties`, downloads the Gradle distribution named by `distributionUrl` (e.g. `gradle-8.7-bin.zip`), unpacks it under `~/.gradle/wrapper/dists/`, and then executes that Gradle. Because the wrapper *runs* the downloaded code, the integrity of that download is a supply-chain concern. ## The property `distributionSha256Sum` is an optional key in `gradle-wrapper.properties`: ```properties distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d ``` When present, after downloading the archive the wrapper computes its SHA-256 and compares it to this value. **Mismatch ⇒ the build fails immediately**, before unpacking or running anything. So an attacker who can serve a different ZIP (compromised mirror, poisoned cache, MITM on a non-HTTPS or intercepted connection) cannot get their code executed — the hash won't match. ## Why HTTPS isn't enough HTTPS protects bytes *in transit* from the server you connected to. The checksum additionally protects against a compromised or malicious server/mirror, a poisoned CDN edge, or an internal proxy that rewrites artifacts. It's defense-in-depth and pins the *exact* expected artifact. ## Where the expected value comes from Gradle publishes the SHA-256 for every distribution on its download/checksum pages. You paste that official value. The safest way to *write* it is not to copy by hand but to let the `wrapper` task pin it (covered by the `--gradle-distribution-sha256-sum` flow), but the property itself — its meaning and the verify-on-download behavior — is what matters here. ## Failure behavior If the downloaded archive's hash differs, Gradle prints an error like `Verification of Gradle distribution failed!` showing the expected vs actual sum and stops. This is fail-closed: no Gradle from that download executes. ## Scope note This verifies the *distribution archive*. The wrapper JAR (`gradle-wrapper.jar`) committed in your repo is a separate artifact verified by other means; don't conflate the two.

  • What happens if the property is present but the downloaded archive's hash doesn't match?
    The wrapper fails the build immediately with a 'Verification of Gradle distribution failed!' error showing expected vs actual sum, and never unpacks or executes the distribution.
  • Does distributionSha256Sum verify the gradle-wrapper.jar?
    No. It only verifies the downloaded distribution archive named by distributionUrl. The committed wrapper JAR is a separate artifact verified separately.

saying these in an interview costs you the question

  • Claiming HTTPS makes the checksum redundant — it doesn't cover a compromised mirror/CDN.
  • Saying it verifies the wrapper JAR or the build scripts — it only covers the distribution archive.
  • Thinking it's hashed locally as defense against runtime tampering — it's verified once, at download time.

context

open as a page

In gradle-wrapper.properties, what does distributionUrl control, and what is the practical difference between the '-bin' and '-all' distribution variants?

level: juniorimportance: must knowfreq 70%

basics

~10 s

distributionUrl tells the wrapper which Gradle version to download. The '-bin' zip contains only the runtime; '-all' also bundles sources and documentation so IDEs can show Gradle API docs. Both run builds identically.

open as a page

What are the files that make up the Gradle Wrapper, and what is each one responsible for?

level: juniorimportance: must knowfreq 70%

basics

~10 s

Four committed files: gradlew (Unix script), gradlew.bat (Windows script), gradle/wrapper/gradle-wrapper.jar (the bootstrapping code), and gradle/wrapper/gradle-wrapper.properties (which Gradle version/distribution to use).

open as a page

How do you upgrade the Gradle version used by a project's wrapper, and what command actually regenerates the wrapper files?

level: juniorimportance: must knowfreq 70%

basics

~10 s

Run ./gradlew wrapper --gradle-version 9.0. The built-in wrapper task rewrites gradle-wrapper.properties (and scripts/jar) to point at the requested version, so everyone uses it on the next build.

open as a page

How do you pin the distribution checksum using the wrapper task instead of editing gradle-wrapper.properties by hand?

level: middleimportance: must knowfreq 40%

basics

~10 s

Run the wrapper task with --gradle-distribution-sha256-sum and the official checksum, e.g. ./gradlew wrapper --gradle-version 8.7 --gradle-distribution-sha256-sum <sum>. Gradle writes distributionSha256Sum into gradle-wrapper.properties for you.

open as a page

How do you set up gradle/wrapper-validation in CI, and where in the pipeline should it run?

level: middleimportance: must knowfreq 50%

basics

~20 s

Add the official action (gradle/actions/wrapper-validation, formerly gradle/wrapper-validation-action) as one of the first jobs in your CI workflow, running on every push and pull request. It fails the build if any wrapper jar's checksum is unknown.

open as a page

Why is the committed gradle-wrapper.jar a supply-chain risk, and what does validating it protect against?

level: middleimportance: must knowfreq 55%

basics

~10 s

gradle-wrapper.jar is a binary committed to the repo that runs before any build. If someone tampers with it, it executes arbitrary code on every machine and CI runner. Validating its SHA-256 catches tampering.

open as a page

Why does the Gradle Wrapper pin the build's Gradle version per project, and what problems does that solve?

level: middleimportance: must knowfreq 65%

basics

~10 s

The wrapper records a specific Gradle distribution in the project, so everyone runs the same version. This makes builds reproducible and prevents 'works on my machine' failures from version drift.

open as a page

What does the wrapper-validation action compare against, and why does it allow a set of checksums rather than one?

level: juniorimportance: should knowfreq 30%

basics

~10 s

It computes the SHA-256 of each gradle-wrapper.jar and checks it against the list of checksums Gradle publishes for all its releases. Many valid jars exist (one per version), so it accepts any known-good one.

open as a page

A teammate reports 'Verification of Gradle distribution failed!' after pulling your branch. How do you diagnose and resolve it?

level: middleimportance: should knowfreq 28%

basics

~20 s

It means the downloaded distribution's SHA-256 didn't match distributionSha256Sum. Check whether distributionUrl and the pinned sum are consistent (right version/type), clear the cached partial download, and re-pin via the wrapper task if the sum was wrong.

open as a page

Where do you obtain the correct SHA-256 to pin, and how do you verify you're pinning a trustworthy value?

level: middleimportance: should knowfreq 30%

basics

~20 s

Use the official SHA-256 that Gradle publishes for each distribution on its checksum/download pages. Copy the value for the exact version and archive type you're using; don't compute it from a download you don't trust.

open as a page

What do distributionBase, distributionPath, zipStoreBase and zipStorePath control in gradle-wrapper.properties?

level: middleimportance: should knowfreq 40%

basics

~20 s

They decide where the wrapper stores the downloaded distribution. The *Base keys pick a root (usually GRADLE_USER_HOME, sometimes PROJECT), and the *Path keys give a subdirectory under it. 'distribution' is the unpacked Gradle; 'zipStore' is the downloaded zip.

open as a page

What is the networkTimeout key in gradle-wrapper.properties, and when would you adjust it?

level: middleimportance: should knowfreq 30%

basics

~10 s

networkTimeout sets, in milliseconds, how long the wrapper waits when connecting to and reading from the distribution download. It defaults to 10000 (10s). Raise it on slow or high-latency networks/mirrors where downloads time out.

open as a page

What is the difference between invoking ./gradlew and a system-installed gradle, and which should a team prefer?

level: middleimportance: should knowfreq 55%

basics

~10 s

./gradlew runs the project's pinned Gradle via the committed wrapper; system gradle runs whatever version you installed globally. Teams should prefer ./gradlew for consistency and reproducibility.

open as a page

How do you configure the `Wrapper` task type declaratively in build.gradle.kts instead of passing CLI flags each time?

level: middleimportance: should knowfreq 35%

basics

~10 s

Configure the built-in wrapper task in your build script: set gradleVersion, distributionType, and optionally distributionUrl/networkTimeout. Then ./gradlew wrapper regenerates files using those values without repeating CLI flags.

open as a page

What does the `--distribution-type` option (bin vs all) control when regenerating the wrapper, and when would you choose `all`?

level: middleimportance: should knowfreq 45%

basics

~10 s

--distribution-type picks which Gradle download the wrapper uses: bin (runtime only, smaller) or all (runtime plus sources and Javadoc). Choose all so IDEs can offer Gradle API source navigation and autocomplete.

open as a page

How would you enforce distribution-checksum pinning across many repositories in an organization, and what are the trade-offs?

level: seniorimportance: should knowfreq 18%

basics

~10 s

Require distributionSha256Sum in every gradle-wrapper.properties, enforce it with a CI lint/check that fails when it's missing or mismatched, and standardize upgrades through the wrapper task so the URL and sum are always pinned together.

open as a page

Wrapper validation fails in CI on an existing project. How do you investigate and respond?

level: seniorimportance: should knowfreq 32%

basics

~20 s

Treat it as a potential supply-chain incident, not a flaky test. Identify which jar failed, check git history for who changed it, and compare against a freshly regenerated official jar. Don't run the build until resolved.

open as a page

What's the difference between validating gradle-wrapper.jar and verifying the Gradle distribution via distributionSha256Sum?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Wrapper-jar validation checks the committed bootstrapper jar against Gradle's published checksums. distributionSha256Sum verifies the downloaded Gradle distribution zip. They protect two different artifacts: the jar that runs, and the Gradle it fetches.

open as a page

Your team wants to upgrade Gradle and guarantee everyone (devs and CI) uses the new version. Walk through how gradle-wrapper.properties makes that reproducible and the right way to perform the bump.

level: seniorimportance: should knowfreq 45%

basics

~20 s

Because distributionUrl in gradle-wrapper.properties pins the exact Gradle version and the wrapper ignores any local Gradle, committing the bumped properties file makes everyone use the same version. Bump it with ./gradlew wrapper --gradle-version X, run it twice, then commit.

open as a page

Which wrapper files belong in version control, and what practical pitfalls (line endings, executable bit, .gitignore) trip teams up?

level: seniorimportance: should knowfreq 45%

basics

~10 s

Commit all four wrapper files (gradlew, gradlew.bat, gradle-wrapper.jar, gradle-wrapper.properties). Pitfalls: accidentally gitignoring the jar, losing gradlew's executable bit, and CRLF line endings breaking the Unix script.

open as a page

Walk through what happens, step by step, when a developer runs ./gradlew build on a fresh clone.

level: seniorimportance: should knowfreq 40%

basics

~10 s

gradlew finds Java and runs gradle-wrapper.jar; the jar reads gradle-wrapper.properties, downloads the named Gradle distribution to the cache if absent, then delegates to that Gradle to execute the build task.

open as a page

Your organization is air-gapped and cannot reach services.gradle.org. How do you regenerate the wrapper so builds fetch Gradle from an internal mirror?

level: seniorimportance: should knowfreq 30%

basics

~10 s

Configure the wrapper to use an internal URL: set distributionUrl (in the wrapper task or properties) to your mirror's gradle-9.0-bin.zip. Regenerate with the wrapper task and commit, so every build pulls from the mirror.

open as a page

Why does distributionUrl in gradle-wrapper.properties contain 'https\://' with a backslash, and what file format is this?

level: juniorimportance: nice to knowfreq 15%

basics

~20 s

gradle-wrapper.properties is a standard Java .properties file. In that format ':' is a key/value separator, so the colon in the URL is escaped as ':' to keep it part of the value. Tools generate this automatically.

open as a page

After running `./gradlew wrapper --gradle-version 9.0`, a colleague notices `gradlew` and `gradle-wrapper.jar` are unchanged in git, only the properties file changed. Is that a problem, and how do you ensure the jar/scripts are updated?

level: seniorimportance: nice to knowfreq 20%

basics

~20 s

Not necessarily a problem — the first run only rewrites distributionUrl; it doesn't always regenerate the scripts/jar. Run the wrapper task a second time (now under the new version) so gradlew, gradlew.bat, and gradle-wrapper.jar are regenerated.

open as a page