skip to content

Verification and Integrity

Gradle's dependency verification: a metadata file of expected checksums and trusted PGP keys, plus the workflow to bootstrap and maintain it. Increasingly asked as supply-chain security moves into the build itself.

on this pageshow

explore

questions

20

What is checksum verification in Gradle's dependency verification, and what problem does it solve?

level: juniorimportance: must knowfreq 55%

answer

  1. re-hash on every resolution
  2. verification-metadata.xml component/artifact entries
  3. md5/sha1/sha256/sha512 elements
  4. mismatch -> build fails
  5. integrity, not authorship

basics

~10 s

Gradle records an expected hash (e.g. sha256) for each downloaded artifact in verification-metadata.xml. On every build it re-hashes the file and fails if it differs, proving the artifact wasn't tampered with or swapped.

solid answer

~40 s

Checksum verification is part of Gradle's dependency-verification feature. When enabled, Gradle expects a `verification-metadata.xml` file under `gradle/` that lists, per artifact (jar, pom, module metadata), one or more cryptographic checksums (`md5`, `sha1`, `sha256`, `sha512`). On resolution Gradle computes the hash of each file it pulls from a repository and compares it to the recorded value. A mismatch — or a missing entry, depending on configuration — fails the build. This protects against a compromised or hijacked repository serving a malicious artifact, accidental corruption, or a cache-poisoning man-in-the-middle. It's purely integrity verification ("is this the exact bytes I trust?"), distinct from PGP signature verification which proves *who* published it. Checksums are simple, fast, and don't require any keyring infrastructure.

code

xml · 8 lines
xml
<component group="org.apache.commons" name="commons-lang3" version="3.14.0">
  <artifact name="commons-lang3-3.14.0.jar">
    <sha256 value="d919d904486c037f8d193412da0c92e22a9fa24230b9d67a57855c5c31c7e94e"/>
  </artifact>
  <artifact name="commons-lang3-3.14.0.pom">
    <sha256 value="8b3e9..."/>
  </artifact>
</component>

go deeper

for a junior

Define it: Gradle stores an expected hash per artifact and fails the build if the downloaded file's hash differs. Name sha256 and the verification-metadata.xml file.

for a middle

Explain it verifies every downloaded file (jar/pom/.module), the algorithm choices, and that a missing or mismatched entry fails resolution.

for a senior

Frame it as supply-chain integrity, contrast with signature verification, and note the bootstrapping trust-on-first-use caveat.

for a principal

Position checksum verification within an org-wide artifact-integrity policy: who reviews the generated metadata, how it interacts with an internal proxy/mirror, and when integrity alone is insufficient versus signatures.

## What checksum verification is Gradle's **dependency verification** feature lets you pin the exact bytes of every artifact your build consumes. Checksum verification is one of its two pillars (the other being PGP signatures). It works by storing, for each artifact, a cryptographic hash that Gradle re-computes and compares on every resolution. The data lives in `gradle/verification-metadata.xml`. The presence of this file is what *enables* verification — there is no separate on/off flag in build scripts. A component block looks like: ```xml <component group="com.google.guava" name="guava" version="33.0.0-jre"> <artifact name="guava-33.0.0-jre.jar"> <sha256 value="a42edc9c..." origin="Generated by Gradle"/> </artifact> <artifact name="guava-33.0.0-jre.module"> <sha256 value="7b9f..."/> </artifact> </component> ``` ## What gets verified Gradle verifies **every file** it downloads for a dependency, not just the main jar: the `.jar`, the `.pom`, the Gradle Module Metadata (`.module`), sources/javadoc jars, and even plugin marker artifacts. Each `<artifact>` element carries one or more checksum children. ## The algorithms Valid element names are `<md5>`, `<sha1>`, `<sha256>`, `<sha512>`. `md5` and `sha1` are considered cryptographically broken (collisions are feasible) and exist mainly because some old repos only publish those — Gradle warns if you rely on them alone. **`sha256` is the recommended default**; `sha512` is available when you want maximum strength. ## How the check runs 1. Gradle resolves a configuration and needs file X from a repository. 2. It downloads X (or reads it from the cache) and computes the configured hashes. 3. It looks up the matching `<artifact>` in `verification-metadata.xml`. 4. If a recorded checksum matches → pass. If it differs → **the build fails immediately** with a verification report. If an artifact is *missing* from the metadata, behavior depends on the `verify-metadata`/strict configuration: by default a missing entry is also a failure, which is the point — an attacker can't sneak in a new transitive dependency unnoticed. ## Bootstrapping You don't hand-write hashes. Run: ```bash ./gradlew --write-verification-metadata sha256 help ``` Gradle resolves the requested tasks, downloads everything, and writes the computed `sha256` values into the file with `origin="Generated by Gradle"`. You then **review and commit** that file. From then on any tampered or substituted artifact produces a different hash and breaks the build. ## Why it matters A public repository (or a mirror/proxy in front of it) is part of your supply chain. If it's compromised and serves a backdoored `log4j.jar` with the same coordinates, only an integrity check catches it. Checksum verification gives you that with zero key-management overhead — its weakness is bootstrapping trust (you trust whatever bytes you first hashed), which is exactly why teams review the generated file and combine it with signature verification for stronger provenance.

  • Does checksum verification tell you who published an artifact?
    No. A checksum only proves the bytes match what you recorded (integrity). Proving the publisher's identity requires PGP signature verification, which checks a signature against a trusted key.
  • Which files of a dependency get verified — just the jar?
    All downloaded files: the jar, pom, Gradle Module Metadata (.module), and sources/javadoc/plugin-marker artifacts. Each is a separate <artifact> entry with its own checksum.

Like a tamper-evident seal on a package: you recorded the seal's serial number once; if the number on delivery differs, you refuse the box — even if the label looks right.

saying these in an interview costs you the question

  • Saying checksums verify the publisher's identity — that's signatures, not hashes.
  • Thinking only the main jar is checked (the pom and .module are also verified).
  • Claiming you must type the hashes by hand instead of generating them.

context

open as a page

What is the verification-metadata.xml file in Gradle, where does it live, and what is its purpose?

level: juniorimportance: must knowfreq 55%

basics

~10 s

It's an XML file at gradle/verification-metadata.xml that lists trusted checksums and/or signatures for every dependency and plugin Gradle resolves. When present and enabled, Gradle verifies each artifact against it before use.

open as a page

What does PGP signature verification in Gradle's dependency verification feature actually verify, and how does it differ from a checksum?

level: juniorimportance: must knowfreq 45%

basics

~10 s

PGP verification checks that a dependency's .asc signature file was produced by a trusted publisher's private key, proving authenticity. A checksum only proves the bytes match a recorded hash, not who produced them.

open as a page

Walk through the practical workflow for keeping verification-metadata.xml current as your project adds and upgrades dependencies over time. What goes wrong if you do it carelessly?

level: middleimportance: must knowfreq 40%

basics

~20 s

When you change dependencies, re-run --write-verification-metadata to append new entries, review the diff in your PR, and commit it. If you skip this, the build fails with 'artifact not in verification metadata'. Regenerating blindly can silently trust tampered artifacts.

open as a page

How do you initially generate Gradle's verification-metadata.xml file, and what does the --write-verification-metadata flag actually do during the build?

level: middleimportance: must knowfreq 55%

basics

~10 s

Run the build with --write-verification-metadata <checksums>, e.g. ./gradlew build --write-verification-metadata sha256. Gradle resolves all dependencies and writes their computed checksums into gradle/verification-metadata.xml.

open as a page

How do you bootstrap sha256 checksums for an existing project, and what is the exact command?

level: middleimportance: must knowfreq 50%

basics

~10 s

Run ./gradlew --write-verification-metadata sha256 help. Gradle resolves dependencies, computes sha256 for every downloaded file, and writes them into gradle/verification-metadata.xml. You then review and commit the file.

open as a page

What does the <configuration> block of verification-metadata.xml contain, and what do verify-metadata and verify-signatures control?

level: middleimportance: must knowfreq 45%

basics

~10 s

The <configuration> block holds global switches: <verify-metadata> toggles checking POM/module metadata files (not just jars), and <verify-signatures> turns on PGP signature checking in addition to checksums.

open as a page

How do you bootstrap PGP verification entries, and what does `--write-verification-metadata pgp,sha256` do?

level: middleimportance: must knowfreq 50%

basics

~10 s

Run gradle --write-verification-metadata pgp,sha256 <task>. Gradle resolves dependencies, downloads each .asc, fetches keys, and writes <trusted-keys> plus <sha256> fallbacks into verification-metadata.xml so you don't hand-author every entry.

open as a page

Which checksum algorithms does Gradle support for verification, and which should you choose and why?

level: middleimportance: should knowfreq 40%

basics

~10 s

Gradle supports md5, sha1, sha256, and sha512. Prefer sha256 (or sha512). md5 and sha1 are cryptographically broken — collisions are feasible — so don't rely on them alone; Gradle even warns about them.

open as a page

How are per-component <artifact> entries structured in verification-metadata.xml, and why does a single component list multiple artifacts?

level: middleimportance: should knowfreq 38%

basics

~10 s

Each <component> identifies a group/name/version and contains one <artifact> per concrete file (the jar, the .pom, the .module, sources/javadoc). Each <artifact> carries the trusted checksum(s) like <sha256> for that exact file.

open as a page

Once verification-metadata.xml exists, what causes a Gradle build to fail verification, and how does Gradle present the failures?

level: middleimportance: should knowfreq 35%

basics

~20 s

The build fails if a downloaded artifact's recomputed checksum/signature doesn't match the recorded value, or if an artifact has no entry at all (and no trust rule). Gradle reports each failing artifact and writes an HTML report you can open.

open as a page

How do `<trusted-keys>` / `<trusted-key>` and per-artifact `<pgp>` entries express trust, and how do you scope a key to specific dependencies?

level: middleimportance: should knowfreq 40%

basics

~10 s

A global <trusted-key id="fingerprint"> trusts that key for any artifact (optionally narrowed with group/name/version). A per-artifact <pgp value="keyId"/> under a <component> trusts a key only for that one artifact.

open as a page

When you regenerate verification metadata with the `pgp` mode, how do you keep PGP key lookups fast and offline-friendly, and what is the keyring export file for?

level: seniorimportance: should knowfreq 35%

basics

~10 s

Add --export-keys when writing metadata so trusted public keys are exported to a local keyring (gradle/verification-keyring.keys). Builds then read keys locally instead of hitting keyservers, making PGP verification faster and offline-capable.

open as a page

What problem does the `--refresh-keys` flag solve, and how does it differ from regenerating metadata with `--write-verification-metadata`?

level: seniorimportance: should knowfreq 28%

basics

~20 s

--refresh-keys re-fetches PGP public keys from key servers and rebuilds the local keyring without changing your trust entries or checksums. Use it when a signer's key was updated/expired so builds can validate signatures again, without re-recording dependency trust.

open as a page

After bootstrapping verification, how do you express trust at different granularities — e.g. trusting a specific key only for one artifact versus globally — when maintaining verification-metadata.xml?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Use <trusted-key> in the <configuration> block for global trust of a key (optionally scoped by group/module), and per-artifact <pgp value="keyid"/> entries under a component for narrow trust. Narrower scoping limits blast radius if a key is misused.

open as a page

What happens during a build when a recorded checksum no longer matches a downloaded artifact, and how would you diagnose it?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Gradle fails the build with a 'Dependency verification failed' error naming the artifact, the expected checksum, and the actual one. You diagnose by checking whether the version/repo changed, the artifact was re-published, or something tampered with it.

open as a page

How does checksum verification differ from PGP signature verification, and when is a checksum alone insufficient?

level: seniorimportance: should knowfreq 35%

basics

~20 s

A checksum proves the bytes equal what you recorded (integrity), trust-on-first-use. A PGP signature proves who published the artifact (authenticity) via a trusted key. Checksums alone can't tell if the bytes you first recorded were already malicious.

open as a page

What is the <trusted-artifacts> block in verification-metadata.xml for, and what are the risks of using it broadly?

level: seniorimportance: should knowfreq 30%

basics

~10 s

<trusted-artifacts> lists <trust> rules (by group, name, version, file, or regex) that exempt matching artifacts from verification entirely. It's useful for locally built or internal artifacts, but broad rules silently disable integrity checks.

open as a page

A build fails with a signature verification error after adding or bumping a dependency. How do you diagnose and resolve it without weakening security?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Read the report at build/reports/dependency-verification/, identify whether the key is untrusted, missing, or the signature is genuinely bad. Re-run --write-verification-metadata pgp,sha256 --export-keys to add legitimate new keys after verifying the fingerprint; never just delete verification or blanket-trust.

open as a page

How does Gradle obtain the public keys it needs to verify signatures, and why prefer a committed keyring over key servers?

level: seniorimportance: should knowfreq 35%

basics

~10 s

Gradle fetches signing public keys from configured <key-servers> (e.g. keyserver.ubuntu.com) or from a committed local keyring (verification-keyring.keys/.gpg). Prefer the keyring: it removes a flaky, attackable network call and makes builds reproducible and offline-capable.

open as a page