Vérification des dépendances

Les dépendances Gradle compromises présentent un risque de sécurité. Un acteur malveillant peut potentiellement injecter une dépendance modifiée dans le processus de compilation, par exemple via une attaque de l'intercepteur lors de la résolution des dépendances.

Si une dépendance de compilation (une bibliothèque) a été compromise, cela peut affecter la façon dont votre application s'exécute sur un appareil. Si une dépendance de plug-in a été compromise, elle peut modifier le fonctionnement de votre build ou même exécuter des commandes externes sur la machine de compilation.

Pour limiter ce problème, vous pouvez activer la vérification des dépendances dans votre compilation.

Sommes de contrôle et signatures des bibliothèques

Les auteurs de la bibliothèque peuvent fournir deux éléments de métadonnées qui peuvent aider à vérifier l'authenticité des dépendances que vous téléchargez. Vous définissez un fichier nommé gradle/verification-metadata.xml pour spécifier les valeurs que vous approuvez. Il peut contenir:

  • Sommes de contrôle : hachage d'un artefact que vous pouvez utiliser pour vérifier qu'il n'a pas été corrompu lors du transport. Si la somme de contrôle a été récupérée à partir d'une source fiable, cela vous indique que l'artefact n'a pas changé, ce qui réduit les attaques de l'intercepteur.

    L'inconvénient est que, comme les sommes de contrôle sont calculées à partir des artefacts, elles changent à chaque version, ce qui vous oblige à mettre à jour gradle/verification-metadata.xml chaque fois que vous les mettez à niveau.

  • Signatures : permet aux utilisateurs de dépendances de spécifier une clé publique pour un artefact donné afin de valider que cet artefact a été créé et signé par l'auteur de la bibliothèque, qui est le propriétaire authentifié de cette clé publique. Cela représente plus de travail pour l'auteur de la bibliothèque, mais tant que sa clé privée n'a pas été compromise, la signature vous indique que la bibliothèque est légitime.

    Si l'auteur de la bibliothèque signe chaque version d'un artefact avec la même clé, vous n'avez pas besoin de mettre à jour gradle/verification-metadata.xml lorsque vous les mettez à niveau.

Activer la validation des dépendances

La vérification des dépendances Gradle compare les sommes de contrôle et les signatures lors de votre compilation.

Créez un fichier gradle/verification-metadata.xml contenant les éléments suivants:

<?xml version="1.0" encoding="UTF-8"?>
<verification-metadata
    xmlns="https://schema.gradle.org/dependency-verification"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://schema.gradle.org/dependency-verification https://schema.gradle.org/dependency-verification/dependency-verification-1.3.xsd">
    <configuration>
        <!-- verify .pom and .module files -->
        <verify-metadata>true</verify-metadata>
        <!-- verify .asc PGP files that come with the artifacts -->
        <verify-signatures>true</verify-signatures>
        <!-- use human readable keyring format -->
        <keyring-format>armored</keyring-format>
        <!-- read keys in a local file, fewer requests to network -->
        <key-servers enabled="false">
            <key-server uri="https://keyserver.ubuntu.com"/>
            <key-server uri="https://keys.openpgp.org"/>
        </key-servers>
    </configuration>
    <components>
    </components>
</verification-metadata>

Il s'agit d'un point de départ qui sera bientôt mis à jour.

Exécutez ./gradlew assembleDebug pour voir comment cela modifie la compilation. Vous verrez des messages comme :

* What went wrong:
Error resolving plugin [id: 'com.android.application', version: '8.7.3', apply: false]
> Dependency verification failed for configuration 'detachedConfiguration1'
  One artifact failed verification: com.android.application.gradle.plugin-8.7.3.pom ...
  This can indicate that a dependency has been compromised ...
  
  Open this report for more details: .../dependency-verification-report.html

Gradle vous indique que vous récupérez des versions de dépendances que vous n'avez pas explicitement approuvées.

Amorcer les données de somme de contrôle et de signature

Vous pouvez amorcer l'ensemble initial de clés et de composants approuvés. Ce processus rassemble les signatures et les sommes de contrôle actuelles de toutes les bibliothèques utilisées par votre projet.

Générer les métadonnées initiales en exécutant

./gradlew --write-verification-metadata pgp,sha256 --export-keys help

Cette commande indique à Gradle de créer une liste de clés PGP et de sommes de contrôle de remplacement pour toutes les dépendances utilisées dans ce projet. Votre fichier verification-metadata.xml sera modifié avec un certain nombre d'entrées, par exemple:

<trusted-key id="8461EFA0E74ABAE010DE66994EB27DB2A3B88B8B">
    <trusting group="androidx.activity"/>
</trusted-key>

Cela indique à Gradle que s'il détecte une dépendance du groupe Maven androidx.activity, il s'assurera que les fichiers .asc associés (signatures stockées dans le dépôt) correspondent à cette clé.

Le démarrage automatique génère également gradle/verification-keyring.keys qui contient les clés PGP publiques utilisées par votre build. Enregistrez ces deux fichiers dans votre système de suivi des versions. Toute modification future qui modifie verification-metadata.xml ou verification-keyring.keys doit être examinée attentivement.

Supprimer les versions des clés approuvées

Les clés de signature changent rarement entre les versions d'une bibliothèque. Les données générées dans le fichier gradle/verification-metadata.xml contiennent des informations sur les versions, ce qui signifie que vous devrez ajouter à nouveau des informations clés pour chaque nouvelle version de dépendance.

Pour éviter cela et spécifier que la clé s'applique à toutes les versions d'une bibliothèque, supprimez les spécifications de version.

Dans l'éditeur Android Studio, utilisez Edit > Find > Replace (Édition > Rechercher > Remplacer) avec une expression régulière pour remplacer toutes les spécifications de version des clés approuvées.

  • de: <trusted-key(.*) version=\".*\"/>
  • à: <trusted-key$1/>

Synchronisation Android Studio

Jusqu'à présent, votre compilation de ligne de commande fonctionne, mais si vous essayez de synchroniser dans Android Studio, des erreurs s'affichent, par exemple :

A build operation failed.
    Dependency verification failed for configuration ':app:detachedConfiguration3'
One artifact failed verification: gradle-8.10.2-src.zip (gradle:gradle:8.10.2) from repository Gradle distributions
If the artifacts are trustworthy, you will need to update the gradle/verification-metadata.xml file. For more on how to do this, please refer to https://docs.gradle.org/8.10.2/userguide/dependency_verification.html#sec:troubleshooting-verification in the Gradle documentation.

Android Studio souhaite télécharger les sources Gradle (avec d'autres sources et documents). Le moyen le plus simple de corriger ce problème consiste à approuver tous les sources et javadocs. Ajoutez <trusted-artifacts> dans gradle/verification-metadata.xml:

<verification-metadata ...>
   <configuration>
      <trusted-artifacts>
         <trust file=".*-javadoc[.]jar" regex="true"/>
         <trust file=".*-sources[.]jar" regex="true"/>
         <trust group="gradle" name="gradle"/>
      </trusted-artifacts>
      ...
  </configuration>
</verification-metadata>

Votre build fonctionnera désormais correctement à partir de la ligne de commande et d'Android Studio.