Skip to content

Hosted Maven rewriter ignores <classifier> and suffixes sources/tests/native classifier dependencies, which breaks the build #262

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

find_maven_dependency_matches matches on groupId + artifactId only. It reads <type> but never <classifier>. A hosted grant is for the main jar only: the served maven2 tail exposes only <a>-<sfx>.jar/.pom and their sidecars. Even so, every classifier variant of the same GA whose literal version equals the base gets rewritten to <base>-socket.<hex8>. Examples of such variants: sources, tests, javadoc, and native classifiers like linux-x86_64.

Impact

  • Broken builds. The suffixed classifier artifact does not exist anywhere. The Socket repo 404s …-socket.<hex8>-sources.jar, and Central has no such version.
  • Silent fail-open when the main jar is only transitive. Take a pom that declares only a classifier variant, while the main jar comes in transitively. The classifier literal counts as "versioned", so no <dependencyManagement> pin is added for the main jar. The main jar then resolves unpatched from Central.

Real-world shapes this hits:

  • netty native transports (netty-transport-native-epoll:linux-x86_64)
  • -tests jars
  • sources for IDE builds

Repro

The grant is the same one as in the basic golden, for org.apache.commons:commons-lang3:3.12.0 → 3.12.0-socket.4d5e6f70. Run scan --mode hosted --json --yes, then Maven 3.9.6 dependency:3.6.1:copy-dependencies, with the stub Socket repo mirrored in via settings.xml.

Case 1, the main jar plus a sources jar. Both <version>3.12.0</version> lines get rewritten:

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency>
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version><classifier>sources</classifier></dependency>

Results:

  • Scan: redirected: 1, no warnings.
  • Maven fetches the patched main jar from the Socket repo, then requests …/3.12.0-socket.4d5e6f70/commons-lang3-3.12.0-socket.4d5e6f70-sources.jar (404). BUILD FAILURE.
  • On 3.9.6 the error surfaces as Cannot invoke "org.eclipse.aether.artifact.Artifact.isSnapshot()" …, because of a resolver NPE with trusted checksums enabled. On 3.8.9/3.9.16 it is Could not find artifact.

Case 2, only the sources classifier is declared, and the main jar is transitive via commons-text:1.10.0:

  • Scan: redirected: 1.
  • Maven downloads commons-lang3-3.12.0.jar (unpatched) from Central, and the build then fails on the suffixed sources jar.
  • With the build fixed by hand (sources dep reverted), the project is silently unpatched, because no depMgmt pin was ever added.

Expected vs actual

  • Expected: only a <dependency> with no <classifier> (or an empty one) and type jar is the grant's target.
    • A classifier variant with the base literal is left alone, with a warning (for example redirect_maven_classifier_unsupported).
    • The main-jar decision (literal rewrite vs. depMgmt pin) is made from the classifier-less matches only.
  • Actual: every classifier variant is suffixed, and the depMgmt fallback is suppressed.

CLI revision

3efdc31d

Suggested fix

  • Capture <classifier> in MavenDependencyMatch.
  • Filter matches to classifier.is_none() && type in {None, "jar"} before the versioned / depMgmt logic.
  • Warn on the others.
  • Add goldens classifier-sources-sibling and classifier-only-transitive-main.
  • Mirror the change in the depscan TS twin.

File refs (at 3efdc31)

  • crates/socket-patch-core/src/patch/redirect/mod.rs:5840-5899 (MavenDependencyMatch has no classifier; find_maven_dependency_matches)
  • crates/socket-patch-core/src/patch/redirect/mod.rs:6090-6170 (the versioned / depMgmt decision)

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions