Skip to content

Hosted Maven Trusted Checksums are silently inert on Maven 3.9.0–3.9.3 (docs and the test gate claim ≥3.9 enforces) #258

Description

[agent] Filed by Claude Code on behalf of Mikola Lysenko (@mikolalysenko) while adding Maven patch SBOM annotations to depscan. Repro artifacts were produced with real Maven and a stub patch API.

Summary

The .mvn/maven.config + .mvn/checksums/checksums.sha256 pair written by the hosted rewriter is not enforced by Maven 3.9.0 through 3.9.3:

  • 3.9.0 / 3.9.1: ${session.rootDirectory} in maven.config is not interpolated, so the summary file is never found. An absolute basedir does work.
  • 3.9.2 / 3.9.3: …trustedChecksums.checksumAlgorithms=SHA-256 is ignored, and only SHA-1 is checked. With failIfMissing=true the error names [SHA-1], and a checksums.sha1 summary is enforced.
  • 3.9.4 and later, 3.10.0-rc-1 and 4.0.0-rc-7 reject a mismatch.

docs/ecosystems.md says the feature "requires Maven 3.9+" and that "On Maven 3.9.0–3.9.8 a mismatch is enforced but reported unclearly". The test helper Mvn::enforces_trusted_checksums returns true for every 3.9.x. CI runs only 3.9.16, so neither claim is ever exercised on the affected releases.

Impact

On 3.9.0–3.9.3, the "independent client-side content pin" does not exist. A jar re-signed with a matching .sha1 (a compromised origin or mirror, or a MITM controlling both files) installs, and the build passes. The suffix still fails closed against Central, so the gap is specifically tampering on the Socket-served path.

Repro

These are the socket-patch-written files, end to end:

  1. scan --mode hosted on the basic golden pom (commons-lang3 3.12.0, with a real patched jar and a suffixed pom served by a stub under socket-patch-<uuid> via a settings.xml mirror). It writes the exact 6-line maven.config and two checksums.sha256 lines.
  2. Tamper the served jar and recompute its .sha1, so the transport check passes.
  3. Run mvn -B -s settings.xml -Dmaven.repo.local=<fresh> dependency:3.6.1:copy-dependencies on each version.
mvn 3.9.0:        rc=0 loadedTrusted=0 mismatch=0  -> TAMPERED jar installed
mvn 3.9.1:        rc=0 loadedTrusted=0 mismatch=0  -> TAMPERED jar installed
mvn 3.9.2:        rc=0 loadedTrusted=0 mismatch=0  -> TAMPERED jar installed
mvn 3.9.3:        rc=0 loadedTrusted=0 mismatch=0  -> TAMPERED jar installed
mvn 3.9.4:        rc=1 "Loaded 1 trusted checksums …"  "trusted checksum mismatch"
mvn 3.9.6:        rc=1 (same)
mvn 3.10.0-rc-1:  rc=1 "Checksum validation failed, expected '<x>' (PROVIDED) … (Trusted Checksums Source: summaryFile)"
mvn 4.0.0-rc-7:   rc=1 (same as 3.10)

An independent probe against Central's commons-lang3 with an all-zero summary gives the same boundary: rc=0 on 3.9.0–3.9.3 and rc=1 on 3.9.4–3.9.16. It also confirms the SHA-1/rootDirectory split above.

Harness note: resolver 2 (3.10 / 4.0) words the failure differently ("Checksum validation failed … Trusted Checksums Source"). Anything grepping for trusted checksum mismatch false-fails there. The capstone's contains("checksum") && contains(sha256) check still holds.

Expected vs actual

  • Expected: the docs and test gate state the real floor (3.9.4). Either the CLI emits a config that 3.9.0–3.9.3 also enforce, or it warns that those versions get transport-only protection.
  • Actual: the docs claim enforcement on all 3.9.x, and the test helper would treat a 3.9.0–3.9.3 leg as enforcing and fail it, but no such leg exists.

CLI revision

3efdc31d. Maven dists from archive.apache.org, JDK 26 (Homebrew), macOS arm64.

Suggested fix

  1. Change enforces_trusted_checksums to (3,9,4)+.
  2. Add CI legs for 3.9.3 (last non-enforcing) and 3.9.4 (first enforcing).
  3. Fix docs/ecosystems.md:164-169 and the CHANGELOG entry.
  4. Optionally, also write a checksums.sha1 summary (enforced from 3.9.2). The ${session.rootDirectory} limitation on 3.9.0/3.9.1 has no workaround short of an absolute path, so document ≥3.9.2 or ≥3.9.4.

File refs (at 3efdc31)

  • crates/socket-patch-cli/tests/maven_build_common/mod.rs:186-189
  • docs/ecosystems.md:157-169
  • .github/workflows/ci.yml:981-993 (only 3.9.16)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions