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 no distributionSha256Sum in the generated gradle-wrapper.properties file, there is no checksum check. And, even if you add distributionSha256Sum 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 associated distributionUrl, 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 add distributionSha256Sum if you do not have it already. Similarly, if you have distributionSha256Sum in the gradle-wrapper.properties file already, when Android Studio changes distributionUrl, it does not change the associated distributionSha256Sum. You will get the error shown above and will need to change distributionSha256Sum 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.