Verificação de dependência

Dependências do Gradle comprometidas representam um risco de segurança. Um agente malicioso pode injetar uma dependência modificada no processo de build, por exemplo, por um ataque man-in-the-middle durante a resolução de dependências.

Se uma dependência de build (uma biblioteca) for comprometida, isso poderá afetar a forma como seu aplicativo é executado em um dispositivo. Se uma dependência de plug-in for comprometida, ela poderá mudar a forma como o build funciona ou até mesmo executar comandos externos na máquina de build.

Para minimizar isso, ative a verificação de dependências no seu build.

Somas de verificação e assinaturas de biblioteca

Os autores da biblioteca podem fornecer dois metadados que podem ajudar a verificar a autenticidade das dependências que você está fazendo o download. Você define um arquivo chamado gradle/verification-metadata.xml para especificar quais valores são aprovados. Ele pode conter:

  • Checksums: um hash de um artefato que pode ser usado para verificar se o artefato não foi corrompido durante o transporte. Se a soma de verificação foi recuperada de uma fonte confiável, ela informa que o artefato não mudou, reduzindo os ataques man-in-the-middle.

    A desvantagem é que, como as somas de verificação são calculadas com base nos artefatos, elas mudam a cada versão, exigindo que você atualize gradle/verification-metadata.xml sempre que fizer upgrade.

  • Assinaturas: permite que os usuários de dependência especifiquem uma chave pública para um determinado artefato para validar que ele foi criado e assinado pelo autor da biblioteca, que é o proprietário autenticado dessa chave pública. Isso é mais trabalho para o autor da biblioteca, mas, desde que a chave particular não tenha sido comprometida, a assinatura informa que a biblioteca é legítima.

    Se o autor da biblioteca assinar cada versão de um artefato com a mesma chave, não será necessário atualizar gradle/verification-metadata.xml ao fazer upgrade.

Ativar a verificação de dependência

A verificação de dependência do Gradle compara somas de verificação e assinaturas durante o build.

Crie um arquivo gradle/verification-metadata.xml que contenha o seguinte:

<?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>

Isso serve como ponto de partida e será atualizado em breve.

Execute ./gradlew assembleDebug para saber como isso muda o build. Você vai receber mensagens como

* 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

O Gradle está informando que você está extraindo versões de dependências que não foram explicitamente aprovadas.

Inicializar a soma de verificação e os dados de assinatura

É possível inicializar o conjunto inicial de chaves e componentes confiáveis. Esse processo reúne as assinaturas e somas de verificação atuais de todas as bibliotecas usadas pelo projeto.

Gere os metadados iniciais executando

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

Esse comando instrui o Gradle a criar uma lista de chaves PGP e checksums de fallback para todas as dependências usadas neste projeto. Você vai notar uma mudança no arquivo verification-metadata.xml com várias entradas, como:

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

Isso informa ao Gradle que, se ele encontrar uma dependência do grupo maven androidx.activity, ele vai garantir que os arquivos .asc (assinaturas armazenadas no repositório) correspondentes correspondam a essa chave.

O bootstrap também gera gradle/verification-keyring.keys, que contém as chaves PGP públicas usadas pelo build. Verifique esses dois arquivos no seu sistema de acompanhamento de versões. Todas as mudanças futuras que modifiquem verification-metadata.xml ou verification-keyring.keys precisam ser cuidadosamente analisadas.

Remover versões de chaves confiáveis

As chaves de assinatura raramente mudam entre as versões de uma biblioteca. Os dados gerados no arquivo gradle/verification-metadata.xml contêm detalhes da versão, o que significa que você precisa adicionar novamente as informações principais para cada nova versão de dependência.

Para evitar isso e especificar que a chave se aplica a todas as versões de uma biblioteca, remova as especificações de versão.

No editor do Android Studio, use Edit > Find > Replace… com uma expressão regular para substituir todas as especificações de versão de chaves confiáveis.

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

Sincronização do Android Studio

Até agora, o build da linha de comando funciona, mas, se você tentar sincronizar no Android Studio, erros como estes vão aparecer:

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.

O Android Studio quer fazer o download das origens do Gradle (junto com outras origens e documentos). A maneira mais fácil de corrigir isso é confiar em todas as fontes e javadocs. Adicionar <trusted-artifacts> em 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>

Agora, o build vai funcionar corretamente na linha de comando e no Android Studio.