Skip to content

Vendored Maven repo only ships .sha1 sidecars, so with aether.checksums.algorithms=SHA-256/SHA-512 Maven 3.8/3.9 silently build Central's unpatched jar (and Maven 4 fails the build) #394

Description

[agent] Found by the scheduled Maven bug-hunt routine (ledger #318).

Summary

vendor writes the committed maven2 tree .socket/vendor/maven/<uuid>/… with only <file>.sha1 sidecars, and wires it as a file:// <repository> with checksumPolicy=fail. Projects that harden Maven's checksums by setting the resolver's aether.checksums.algorithms to SHA-256 and/or SHA-512 without SHA-1 (via -D… or .mvn/maven.config) get this:

  • Maven 3.8.8 / 3.9.11: the vendored repo has no checksum in the configured algorithms, so the fail policy rejects it with no warning at all. The resolver moves on to Central, which is under the default warn policy, and downloads the pristine jar. BUILD SUCCESS, exit 0, unpatched bytes.
  • Maven 4.0.0-rc-7: the build fails with Could not transfer artifact … from/to socket-patch-vendor-<uuid> … Checksum validation failed, no checksums available. That is fail-closed, but vendoring breaks a build that worked before.
  • vex (online or --offline) on the fresh checkout still emits not_affected / inline_mitigations_already_exist "(vendored)". It prints a stderr warning that the live tree differs, but still makes the attestation.

Impact

Users who opt into SHA-256/512-only checksums are the most security-conscious ones, and for them the vendored patch is silently skipped while VEX says it's applied. Nothing in socket-patch's or Maven's output flags it.

Repro (Linux, JDK 21, Maven 3.9.11)

  1. Consumer pom.xml depends on org.apache.commons:commons-text:1.10.0. Warm a fresh -Dmaven.repo.local.
  2. Stage .socket/manifest.json + blob: a patch that appends a marker to META-INF/NOTICE.txt, with real git-sha256 before/after hashes (the same shape as crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs::stage_manifest).
  3. Run socket-patch vendor --json --offline --cwd proj. It reports applied: 1 and wires file://${project.basedir}/.socket/vendor/maven/<uuid> with checksumPolicy=fail.
  4. Fresh checkout: delete the manifest and blobs, and purge org/apache/commons/commons-text from the local repo.
  5. echo '-Daether.checksums.algorithms=SHA-256,SHA-512' > proj/.mvn/maven.config
  6. mvn -B -Dmaven.repo.local=$M2 org.apache.maven.plugins:maven-dependency-plugin:3.1.2:copy-dependencies, then check target/dependency/commons-text-1.10.0.jar for the marker.

Log (3.9.11): one Downloading from socket-patch-vendor-… line, with no WARN/ERROR for it, followed by

[INFO] Downloading from central: …/commons-text-1.10.0.jar
[WARNING] Checksum validation failed, no checksums available from central for …/commons-text-1.10.0.jar
[INFO] Downloaded from central: …/commons-text-1.10.0.jar (238 kB)
BUILD SUCCESS

The jar is PRISTINE. Adding commons-text-1.10.0.{jar,pom}.sha256 + .sha512 sidecars by hand to the vendored leaf makes the same run resolve PATCHED, which confirms the root cause and the fix direction.

Expected vs actual

  • Expected: docs/ecosystems.md (Maven row) and the maven_repo.rs module docs say the committed repo is consumed with checksumPolicy=fail, so that "a tampered jar → checksum failure", and vendored mode must never fall through to the registry silently. The vendored repo should satisfy whichever checksum algorithms Maven is configured for, e.g. by writing .sha256 and .sha512 (and optionally .md5) next to .sha1.
  • Actual: the vendored repo can be validated with SHA-1 only. Under a non-SHA-1 algorithm set it is skipped without a sound, and vex attests anyway.

Matrix (Linux, JDK 21; resolve with maven-dependency-plugin 3.1.2, fresh local repo)

Maven default SHA-512 SHA-256 SHA-512,SHA-1
3.6.3 PATCHED PATCHED (property ignored) PATCHED PATCHED
3.8.8 PATCHED PRISTINE, exit 0 PRISTINE, exit 0 PATCHED
3.9.11 PATCHED PRISTINE, exit 0 (reproduced 3×, via -D and .mvn/maven.config) PRISTINE, exit 0 PATCHED
4.0.0-rc-7 PATCHED build fails on the vendored repo build fails on the vendored repo PATCHED

macOS and Windows are untested. The behaviour is resolver-level, so it's expected to match.

Not bisected: every release that has vendored Maven writes .sha1 only (main f6b7fb9, 4.0.0).

Suspect code

  • crates/socket-patch-core/src/vendor/maven_repo.rs:1015-1037 (write_maven_artifact writes only .sha1)
  • crates/socket-patch-core/src/vendor/maven_repo.rs:23-30 (the design note says sha1 alone is enough)
  • maven_repo.rs:1050-1080: the verify/re-run fast path also checks .sha1 only, so new sidecars would need to join it.

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

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions