Applying distributionSha256Sum to Gradle and Android Studio
Since I wrote about a Gradle Wrapper supply chain attack
a few days ago, I decided to check back in Android Studio’s support for
distributionSha256Sum
. And the good news is that with Android Studio Electric
Eel, it seems to work well… if you know the limitations.
Basic Setup
In your gradle/wrapper/gradle-wrapper.properties
file, there is a
distributionUrl
property that indicates what build of Gradle should be downloaded
and used for building your project:
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
You can add distributionSha256Sum
to gradle/wrapper/gradle-wrapper.properties
as
well. You get the value for your target version of Gradle from the Gradle Web site.
So, for example, for the Gradle 7.5 binary-only ZIP, you will find that the checksum
is cb87f222c5585bd46838ad4db78463a5c5f3d336e5e2b98dc7c0c586527351c2
. So the matching
distributionSha256Sum
line for the above distributionUrl
line is:
distributionSha256Sum=cb87f222c5585bd46838ad4db78463a5c5f3d336e5e2b98dc7c0c586527351c2
This helps prevent a Martian in the middle (MITM) attack that replaces the Gradle
ZIP file with one that has been modified. If Android Studio or the Gradle Wrapper
JAR file tries downloading the ZIP from distributionUrl
, and the resulting
ZIP file does not have a SHA-256 checksum matching distributionSha256Sum
,
Android Studio and Gradle will refuse to use it. Android Studio Electric Eel
will give you output akin to this in the Build tool:
Verification of Gradle distribution failed!
Your Gradle distribution may have been tampered with.
Confirm that the 'distributionSha256Sum' property in your gradle-wrapper.properties file is correct and you are downloading the wrapper from a trusted source.
Distribution Url: https://services.gradle.org/distributions/gradle-7.5-bin.zip
Download Location: /home/mmurphy/.gradle/wrapper/dists/gradle-7.5-bin/f1w0cc9nuo0eivz97x2xlu9sv/gradle-7.5-bin.zip
Expected checksum: '6b47b85e791fa422b9b78bdfab7672dd934ff973d6e781ba98d972e844d91754'
Actual checksum: 'cb87f222c5585bd46838ad4db78463a5c5f3d336e5e2b98dc7c0c586527351c2'
That same message, minus the first line, will also be output by the Gradle Wrapper JAR.
The Limitations
The big wrinkle with distributionSha256Sum
is that it is checked at the point
of downloading the Gradle version specified in the distributionUrl
. If you
already successfully downloaded that version of Gradle before — such as via
a project that lacks distributionSha256Sum
— no further checks are made.
So, it is very easy to think that distributionSha256Sum
is not working, because
you add it to a project, put in an invalid checksum value to test… and the project
still builds. You need to clear out the already-downloaded Gradle distribution
first, forcing a fresh download. Those are stored in ~/.gradle/wrapper/dists
on Linux and macOS (and presumably in an equivalent location on Windows).
This may be less of a problem for CI systems that use fresh containers on each
build.
Also:
-
Android Studio templates do not supply
distributionSha256Sum
, which means you are screwed right out of the box. If you have a new Android Studio version create a new project which uses a new Gradle version, since there is nodistributionSha256Sum
in the generatedgradle-wrapper.properties
file, there is no checksum check. And, even if you adddistributionSha256Sum
yourself manually later, you also have to manually clear out the already-downloaded Gradle to force a checksum check. Since the SHA-256 hash is a known value for the associateddistributionUrl
, it would be very useful if Android Studio’s templates included it. -
If you have Android Studio update your
gradle-wrapper.properties
file to point to a new Gradle version, it does not adddistributionSha256Sum
if you do not have it already. Similarly, if you havedistributionSha256Sum
in thegradle-wrapper.properties
file already, when Android Studio changesdistributionUrl
, it does not change the associateddistributionSha256Sum
. You will get the error shown above and will need to changedistributionSha256Sum
manually.
Those limitations will hamper adoption of distributionSha256Sum
. However,
it still feels like a useful defense, for those who are willing to work around those
limitations.