Dependency Verification, Checksums, Signatures, Repository Content Filtering, and Supply-Chain Security: Diagnostics, Failure Modes, Security, and Performance
Diagnose tampered bytes, repository confusion, broad plugin trust, stale verification baselines, compromised credentials, and poisoned caches as supply-chain incidents. Preserve evidence first; never make the error disappear by disabling the control.
Learning objectives
- Preserve verification and repository evidence before changing caches or metadata.
- Diagnose generated-but-unreviewed metadata, checksum mismatch, repository confusion, and plugin repository sprawl.
- Respond to credential/artifact compromise as an incident rather than a local-cache problem.
- Use isolated fresh state to distinguish cache corruption from remote/repository policy failure.
- Apply the least destructive correction and prove the trust invariant again.
Incident rule. A verification failure is evidence. Do not delete caches, regenerate checksums, disable verification, change repository order, or rotate credentials before recording the failing coordinate, expected/actual digest, repository origin, Wrapper/JDK identities, and relevant logs.
1. Diagnostic sequence for supply-chain failures
| Step | Question | Evidence |
|---|---|---|
| 1. Preserve | What exactly failed before intervention? | Log/report, expected/actual digest, coordinate, repository URL/name, timestamps. |
| 2. Tool identity | Did Wrapper/JDK/build-tool identity change? |
Wrapper properties/JAR digest, --version, JDK
version.
|
| 3. Declared policy | What repositories/verification rules were intended? | settings/build/POM/settings.xml + verification metadata diff. |
| 4. Resolution graph | Which module/plugin and transitive path selected it? | dependency report / dependencyInsight / Maven dependency tree. |
| 5. State/origin | Which cache/repository supplied the bytes? | Isolated fresh user home/local repo; resolver logs. |
| 6. Verify externally | Do independent release digests/key fingerprints match? | Publisher/approved-manager evidence. |
| 7. Correct | What smallest change restores intended trust? | Restore immutable bytes, fix exclusive routing, rotate credentials, reviewed metadata update. |
| 8. Rebuild | Does strict clean-room verification pass? | Fresh isolated build + artifact identity checks. |
2. Failure: verification metadata was auto-accepted
A dependency bot updates a version and runs
--write-verification-metadata sha256; CI commits the
resulting file automatically. The build is green, but nobody
verified whether the new checksums correspond to the intended
publisher.
Diagnosis: inspect the dependency/version diff and verification metadata together. Determine the origin of every new artifact/key. Repair: independently validate the new digest/fingerprint, annotate the review, then run strict verification. If you cannot establish provenance, reject the upgrade rather than accepting the generated baseline.
3. Failure: checksum mismatch
The strict build reports expected digest A and actual digest B for the same coordinate. Possible causes include repository mutation, compromised mirror, inconsistent repository copies, local cache corruption, or an intentional rebuild published under an immutable version.
# Preserve before cleanup:
cp checksum-mismatch.log incident-checksum-mismatch.log
sha256sum path/to/suspect.jar | tee incident-actual.sha256
cp gradle/verification-metadata.xml incident-verification-metadata.xml
cat gradle/wrapper/gradle-wrapper.properties > incident-wrapper.properties
# Then compare in isolated disposable cache state, not normal ~/.gradle:
GRADLE_USER_HOME="$PWD/.incident-gradle-home" \
./gradlew --refresh-dependencies --dependency-verification strict compileJava
If fresh state returns the same unexpected bytes, cache corruption is unlikely. Investigate repository/mirror origin. If fresh state returns the expected bytes, preserve the bad cached artifact before removing only the disposable incident cache.
4. Broken “repair”: turn verification off
This command is diagnostic only and unsafe as a release fix:
# Anti-pattern for a release gate — do not normalize this:
./gradlew --dependency-verification off build
It answers “would the build continue if we ignore the security control?” It does not answer whether the dependency is safe. Restore strict mode and investigate the artifact.
5. Failure: repository order permits dependency confusion
An internal group is declared in a private repository, but a broad public repository is also eligible. An attacker publishes the same coordinate publicly. Normal repository order is operational state and can change with refactors or plugins.
Repair: make the namespace exclusive (or enforce central routing in a repository manager) and prove that removing the internal artifact causes resolution failure rather than public fallback. Do not rely on “our internal repository happens to be first.”
6. Failure: plugin resolution is unrestricted
A project carefully scopes normal dependencies but
pluginManagement.repositories includes multiple broad
repositories and plugin versions drift. Because plugins execute
during build configuration, that is a direct code-execution trust
gap.
Repair: pin plugin versions, reduce/scoped plugin repositories, verify plugin artifacts, and review marker/implementation coordinates. Remember that project dependency repository policy does not automatically govern plugin repositories.
7. Failure: suspected repository credential compromise
Do not respond only by clearing caches. Preserve access/audit logs where available, revoke/rotate the credential through the repository/CI system, block or quarantine the affected publication path, verify whether immutable coordinates were overwritten, and rebuild from independently trusted inputs. Project files should never contain the real secret used for this exercise.
8. Failure: compromised artifact is reused from cache
Cache reuse changes where bytes are read from; it does not change the trust requirement. If a less-trusted job can populate a shared dependency/build cache consumed by privileged jobs, treat that cache as an input boundary. Dependency verification catches altered external dependency bytes only if verification remains enabled and the cache path still goes through verified resolution. Build-cache outputs need their own trust model from Chapter 24.
9. Maven-specific diagnostic boundary
With Maven, capture effective settings/mirrors, repository IDs,
checksum policy, dependency tree, Wrapper properties, and isolated
local-repository results. A repository checksum failure should not
be “fixed” with checksumPolicy=ignore. If signature
authenticity is required, use an independently anchored signature
verification/repository-manager policy rather than claiming Maven
core checksum transport alone proves the publisher.
10. Performance is secondary to correctness
Verification and repository scoping can add network/CPU overhead, especially on first resolution. Measure cold and warm behavior separately. Do not broaden repositories, trust all sources/javadocs, disable verification, or weaken key scope merely to shave seconds from CI. First optimize repository topology, caching, and parallelism without changing the acceptance policy.
11. Interpret the intentionally broken local example
In Lesson 2 the same 1.0.0 coordinate was overwritten.
The expected outcome is a non-zero build with a dependency
verification failure. The important artifact is not the return code
by itself; it is the preserved tuple:
coordinate=dev.academy.internal:policy-lib:1.0.0
repository=academyInternal (trusted-repo)
expected_sha256=<from reviewed verification metadata>
actual_sha256=<from changed artifact>
wrapper=Gradle 9.7.1 + verified wrapper/distribution
jdk=21 runtime / Java 17 target
action=restore trusted immutable bytes; do not accept new checksum
12. Least-destructive repair principle
Fix the trust boundary that failed. Restore artifact bytes if immutability was broken; narrow repository eligibility if routing was wrong; update a checksum/key only after independent review when the dependency upgrade was intentional; rotate credentials if exposure occurred. Then rerun strict verification from isolated state and compare the resolved graph/artifact identity to the intended baseline.
Knowledge check
Why preserve the suspect JAR before clearing a disposable cache?
It may be the only copy of the bytes that triggered the incident and is useful for root-cause comparison.
What does dependency-verification off prove?
Only that the build can proceed without the control; it proves nothing about artifact trust.
How do you prove repository exclusivity works?
Make the exclusive repository unable to serve the coordinate and show resolution fails even if another declared repository contains it.
What additional evidence should accompany a signing-key rotation?
Independent confirmation of the new fingerprint/ownership and a scoped trusted-key policy update.
Why is credential compromise not a cache-cleanup problem?
The credential may have enabled repository mutation or data access; rotation, audit, quarantine, and clean-room verification are required.
Official references and version notes
- Gradle 9.7.1 release notes — pinned Gradle baseline and current dependency-verification diagnostics.
- Verifying Dependencies — checksums, signatures, trusted keys, strict/lenient/off modes, bootstrapping, reports, and scope.
-
Filtering Repository Content
— repository filters and
exclusiveContentsemantics. -
Gradle Wrapper
—
distributionSha256Sum, Wrapper JAR verification, PGP verification, and upgrade workflow. - Securing Gradle Builds — dependency, repository, cache, CI, and Wrapper attack surfaces.
- Maven release history — Maven 3.9.16 GA baseline; Maven 4 remains pre-GA at this chapter timestamp.
- Maven settings reference — repositories, mirrors, servers, and repository policies.
- Maven Resolver RepositoryPolicy — checksum fail/warn/ignore behavior.
- Apache Maven Wrapper — Wrapper 3.3.4 and SHA-256 verification properties.
- Apache Maven downloads — release checksums/signatures and KEYS verification guidance.
Version-sensitive behavior was rechecked against primary documentation on 2026-08-24. Mandatory labs are local/free and use synthetic artifacts only. No production repository, credential, signing key, shared cache, or hosted CI service is required.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.