Verify the Gradle distribution before running it #174

Merged
paulhitt merged 1 commits from chore/verify-the-gradle-distribution into main 2026-09-22 15:05:40 +00:00
paulhitt commented 2026-09-22 14:38:41 +00:00 (Migrated from gitlab.com)

The wrapper downloaded a 164 MB distribution from services.gradle.org
and executed it with no integrity check. Every dependency in this
repository is already pinned to an exact version, with no dynamic
versions anywhere, so the build tool itself was the unchecked part.

distributionSha256Sum is what Gradle provides for this.

Proven cold, because the first attempt proved nothing: setting the
checksum and running ./gradlew --version succeeded with an all-zeros
value too, since Gradle verifies at download time and the distribution
was already extracted here. With the cache moved aside it refuses:

Verification of Gradle distribution failed!
Expected checksum: '0000...0000'
Actual checksum:   'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a'

That is both halves at once. The control is enforced, and Gradle's own
hash of the freshly downloaded artifact is the value pinned here, which
matches what services.gradle.org publishes. The correct checksum then
downloads and runs on the same cold cache.

What this does not defend against: the checksum comes from the same
origin as the distribution, so a compromise of that server right now
would serve both. It does catch a corrupted mirror, a poisoned cache,
and a tampered re-upload later.

Still unverified: the dependency artifacts themselves. Their versions
are exact but there is no verification-metadata.xml, so nothing checks
what comes back from the repositories.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

The wrapper downloaded a 164 MB distribution from services.gradle.org and executed it with no integrity check. Every dependency in this repository is already pinned to an exact version, with no dynamic versions anywhere, so the build tool itself was the unchecked part. `distributionSha256Sum` is what Gradle provides for this. Proven cold, because the first attempt proved nothing: setting the checksum and running `./gradlew --version` succeeded with an all-zeros value too, since Gradle verifies at download time and the distribution was already extracted here. With the cache moved aside it refuses: Verification of Gradle distribution failed! Expected checksum: '0000...0000' Actual checksum: 'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a' That is both halves at once. The control is enforced, and Gradle's own hash of the freshly downloaded artifact is the value pinned here, which matches what services.gradle.org publishes. The correct checksum then downloads and runs on the same cold cache. What this does not defend against: the checksum comes from the same origin as the distribution, so a compromise of that server right now would serve both. It does catch a corrupted mirror, a poisoned cache, and a tampered re-upload later. Still unverified: the dependency artifacts themselves. Their versions are exact but there is no `verification-metadata.xml`, so nothing checks what comes back from the repositories. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
paulhitt commented 2026-09-22 14:38:41 +00:00 (Migrated from gitlab.com)

assigned to @paulhitt

assigned to @paulhitt
paulhitt commented 2026-09-22 15:05:40 +00:00 (Migrated from gitlab.com)

mentioned in commit 55aa2d6f45

mentioned in commit 55aa2d6f4567d7b3609df5f4388d9214766aa577
paulhitt (Migrated from gitlab.com) merged commit 55aa2d6f45 into main 2026-09-22 15:05:40 +00:00
Sign in to join this conversation.