[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:
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.
- Tamper the served jar and recompute its
.sha1, so the transport check passes.
- 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
- Change
enforces_trusted_checksums to (3,9,4)+.
- Add CI legs for 3.9.3 (last non-enforcing) and 3.9.4 (first enforcing).
- Fix
docs/ecosystems.md:164-169 and the CHANGELOG entry.
- 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)
[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.sha256pair written by the hosted rewriter is not enforced by Maven 3.9.0 through 3.9.3:${session.rootDirectory}inmaven.configis not interpolated, so the summary file is never found. An absolute basedir does work.…trustedChecksums.checksumAlgorithms=SHA-256is ignored, and only SHA-1 is checked. WithfailIfMissing=truethe error names[SHA-1], and achecksums.sha1summary is enforced.docs/ecosystems.mdsays 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 helperMvn::enforces_trusted_checksumsreturns 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:
scan --mode hostedon thebasicgolden pom (commons-lang3 3.12.0, with a real patched jar and a suffixed pom served by a stub undersocket-patch-<uuid>via asettings.xmlmirror). It writes the exact 6-linemaven.configand twochecksums.sha256lines..sha1, so the transport check passes.mvn -B -s settings.xml -Dmaven.repo.local=<fresh> dependency:3.6.1:copy-dependencieson each version.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 mismatchfalse-fails there. The capstone'scontains("checksum") && contains(sha256)check still holds.Expected vs actual
CLI revision
3efdc31d. Maven dists from archive.apache.org, JDK 26 (Homebrew), macOS arm64.Suggested fix
enforces_trusted_checksumsto(3,9,4)+.docs/ecosystems.md:164-169and the CHANGELOG entry.checksums.sha1summary (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-189docs/ecosystems.md:157-169.github/workflows/ci.yml:981-993(only 3.9.16)