Skip to content

Update to Resolver 2.0.21#12504

Merged
cstamas merged 1 commit into
apache:maven-3.10.xfrom
cstamas:maven-3.10.x-resolver2
Jul 19, 2026
Merged

Update to Resolver 2.0.21#12504
cstamas merged 1 commit into
apache:maven-3.10.xfrom
cstamas:maven-3.10.x-resolver2

Conversation

@cstamas

@cstamas cstamas commented Jul 18, 2026

Copy link
Copy Markdown
Member

Also add validations.

Fixes #12484

Also add validations.
@cstamas cstamas added this to the 3.10.0 milestone Jul 18, 2026
@cstamas cstamas self-assigned this Jul 18, 2026
@cstamas cstamas added dependencies Pull requests that update a dependency file enhancement New feature or request labels Jul 18, 2026
@cstamas
cstamas marked this pull request as ready for review July 18, 2026 16:31
@cstamas
cstamas requested a review from Copilot July 18, 2026 16:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Maven’s embedded Resolver integration to the targeted 2.0.21 line and wires in additional validation to catch malformed/uninterpolated coordinates and invalid metadata version/path components earlier in the resolution pipeline.

Changes:

  • Bumps the Maven Resolver version property to 2.0.21-SNAPSHOT.
  • Introduces a validating metadata reader and switches multiple metadata read paths to use it.
  • Adds a Resolver Validator + ValidatorFactory to reject placeholder-containing coordinates and validate artifact/metadata components.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pom.xml Updates the Resolver version property used across the build.
maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/metadata/ValidatingMetadataXpp3Reader.java Adds a validating wrapper around MetadataXpp3Reader using Resolver PathUtils validation.
maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenMetadata.java Switches metadata file parsing to the validating reader.
maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionResolver.java Uses validating metadata parsing when reading available versions.
maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionRangeResolver.java Uses validating metadata parsing when reading available versions.
maven-core/src/main/java/org/apache/maven/internal/aether/MavenValidatorFactory.java Adds a ValidatorFactory providing Maven’s validator instance to Resolver.
maven-core/src/main/java/org/apache/maven/internal/aether/MavenValidator.java Adds a Maven-specific Validator to reject placeholders and validate components.
maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/io/DefaultMetadataReader.java Switches metadata reading to the validating reader.
maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/AbstractRepositoryMetadata.java Switches repository metadata update reads to the validating reader.
maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/DefaultRepositoryMetadataManager.java Switches legacy metadata reads to the validating reader.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pom.xml
<cipherVersion>2.0</cipherVersion>
<jxpathVersion>1.4.0</jxpathVersion>
<resolverVersion>2.0.20</resolverVersion>
<resolverVersion>2.0.21-SNAPSHOT</resolverVersion>
Comment on lines +56 to +60
public static Metadata validate(Metadata metadata) {
if (metadata != null) {
PathUtils.validatePathComponent(metadata.getVersion(), "version");
Versioning versioning = metadata.getVersioning();
if (versioning != null) {
Comment on lines +41 to +51
@Override
public void validateArtifact(Artifact artifact) throws IllegalArgumentException {
if (containsPlaceholder(artifact.getGroupId())
|| containsPlaceholder(artifact.getArtifactId())
|| containsPlaceholder(artifact.getVersion())
|| containsPlaceholder(artifact.getClassifier())
|| containsPlaceholder(artifact.getExtension())) {
throw new IllegalArgumentException("Not fully interpolated artifact " + artifact);
}
PathUtils.validateArtifactComponents(artifact);
}

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Update to Resolver 2.0.21

Clean and well-structured update that brings security hardening to Maven 3.10.x via Resolver 2.0.21.

What this PR does well

  • Security hardening — adds ValidatingMetadataXpp3Reader to reject path-traversal attacks in metadata versions, and MavenValidator to catch un-interpolated ${...} placeholders before they reach the resolver
  • Backward compatibility — intentionally omits validateRemoteRepository() (documented with GH-7398 reference), since users commonly have ${env.TOKEN} in repository URLs
  • Consistent pattern — the MavenValidator/MavenValidatorFactory pair follows the established Resolver SPI pattern
  • SNAPSHOT version — standard development workflow for this branch (prior commits show the same SNAPSHOT → release bump pattern)

Observations (informational)

  1. [Low] No dedicated unit tests for ValidatingMetadataXpp3Reader or MavenValidator — the existing integration test MavenITgh12305InvalidCollectRequestUninterpolatedManagedDepsTest exercises the un-interpolated placeholder path, and all 18 CI matrix entries pass. The validation logic itself is straightforward delegation to PathUtils utilities, so integration-level coverage is a reasonable trade-off.

  2. [Info] PathUtils.validatePathComponent() / validateArtifactComponents() / validateMetadataComponents() — these come from the unreleased Resolver 2.0.21. Since the same author (cstamas) wrote both the Resolver PR (apache/maven-resolver#1959) and this Maven PR, and all CI passes, this is low-risk.

  3. [Info] RuntimeException propagation — in some metadata-reading paths (MavenMetadata.read(), DefaultMetadataReader, AbstractRepositoryMetadata), an IllegalArgumentException from validation would propagate uncaught. In the primary version-resolution paths, the broad catch (Exception e) handles it gracefully. For the other paths, failing on invalid metadata is the desired security behavior.

Checklist

Check Status
Tests ✓ Integration tests pass (18/18 CI jobs)
Docs ✓ Javadoc with @since 3.10.0, GH-7398 reference
Commit convention
Public API / backward compat ✓ Internal packages only
Security Positive — adds hardening
CI ✓ All pass

LGTM.


Reviewed with Claude Code on behalf of Guillaume Nodet. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

@ascheman ascheman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, and I verified it end-to-end rather than just reading the diff. (Non-binding review.)

Coverage is complete. git grep 'new MetadataXpp3Reader()' on current maven-3.10.x yields exactly the six files this PR migrates to ValidatingMetadataXpp3Reader — no metadata parse site is left unvalidated.

Wiring is correct. MavenValidatorFactory (@Named @Singleton) is picked up via Sisu collection injection into resolver's DefaultRepositorySystemValidator(List<ValidatorFactory>) — no extra registration needed.

Empirical proof it bites. I built a distribution from the PR head (b4b42148ec, resolver 2.0.21-SNAPSHOT) and resolved a version range [0,) against a hand-crafted maven-metadata.xml whose <version> is ../../../../../../../../tmp/pwned:

  • Baseline 3.10.0-rc-1 (no fix): the traversal string flows straight into a real filesystem path — the resolver tries to open a lock file literally named .../.locks/artifact~org.evil~widget~pom~../../../../../../../../tmp/pwned.lock. The .. segments are live path components; it only fails incidentally, nothing rejects the traversal.
  • This PR: caught at parse time — [WARNING] ... is invalid: Invalid versioning/latest: must not contain '..', '/' or '\': ../../../../../../../../tmp/pwned (IllegalArgumentException at PathUtils.validatePathComponent:91). The bad version is dropped, the range sees no candidates, and the traversal string never reaches any filesystem path.

Nice touch that a poisoned repo is treated as "contributed no usable versions" (per-repository WARNING) rather than a hard build-abort.

Two remarks, neither blocking:

  1. Merge gate (stating the obvious): resolverVersion is 2.0.21-SNAPSHOT; needs released 2.0.21 before this lands — CI is only green via apache-snapshots.
  2. Nit: ValidatingMetadataXpp3Reader.validate() intentionally validates only the version-ish fields, not metadata.groupId/artifactId or snapshotVersions[*].classifier/extension — presumably because those storage paths derive from request-side coordinates, which MavenValidator already covers. A one-line comment saying so would preempt the question for future readers.

@cstamas
cstamas merged commit e2c2b82 into apache:maven-3.10.x Jul 19, 2026
18 checks passed
@cstamas
cstamas deleted the maven-3.10.x-resolver2 branch July 19, 2026 18:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants