This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch maven-3.10.x
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/maven-3.10.x by this push:
new e2c2b82736 Update to Resolver 2.0.21 (#12504)
e2c2b82736 is described below
commit e2c2b82736762a0fa250a1940a73241cf32fbb98
Author: Tamas Cservenak <[email protected]>
AuthorDate: Sun Jul 19 20:06:04 2026 +0200
Update to Resolver 2.0.21 (#12504)
## 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.
---
.../metadata/DefaultRepositoryMetadataManager.java | 4 +-
.../metadata/AbstractRepositoryMetadata.java | 4 +-
.../metadata/io/DefaultMetadataReader.java | 6 +-
.../maven/internal/aether/MavenValidator.java | 91 ++++++++++++++++++++++
.../internal/aether/MavenValidatorFactory.java | 37 +++++++++
.../internal/DefaultVersionRangeResolver.java | 7 +-
.../internal/DefaultVersionResolver.java | 7 +-
.../maven/repository/internal/MavenMetadata.java | 4 +-
.../metadata/ValidatingMetadataXpp3Reader.java | 75 ++++++++++++++++++
pom.xml | 2 +-
10 files changed, 221 insertions(+), 16 deletions(-)
diff --git
a/maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/DefaultRepositoryMetadataManager.java
b/maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/DefaultRepositoryMetadataManager.java
index 54ca354e2b..14f73e1290 100644
---
a/maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/DefaultRepositoryMetadataManager.java
+++
b/maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/DefaultRepositoryMetadataManager.java
@@ -33,8 +33,8 @@
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.DefaultRepositoryRequest;
import org.apache.maven.artifact.repository.RepositoryRequest;
-import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
+import
org.apache.maven.repository.internal.metadata.ValidatingMetadataXpp3Reader;
import org.apache.maven.repository.legacy.UpdateCheckManager;
import org.apache.maven.repository.legacy.WagonManager;
import org.apache.maven.wagon.ResourceDoesNotExistException;
@@ -270,7 +270,7 @@ protected Metadata readMetadata(File mappingFile) throws
RepositoryMetadataReadE
Metadata result;
try (Reader reader = ReaderFactory.newXmlReader(mappingFile)) {
- MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
+ ValidatingMetadataXpp3Reader mappingReader = new
ValidatingMetadataXpp3Reader();
result = mappingReader.read(reader, false);
} catch (FileNotFoundException e) {
diff --git
a/maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/AbstractRepositoryMetadata.java
b/maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/AbstractRepositoryMetadata.java
index 82bd9fea5a..2b97665f5d 100644
---
a/maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/AbstractRepositoryMetadata.java
+++
b/maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/AbstractRepositoryMetadata.java
@@ -27,8 +27,8 @@
import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
-import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
+import
org.apache.maven.repository.internal.metadata.ValidatingMetadataXpp3Reader;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@@ -64,7 +64,7 @@ public void storeInLocalRepository(ArtifactRepository
localRepository, ArtifactR
protected void updateRepositoryMetadata(ArtifactRepository
localRepository, ArtifactRepository remoteRepository)
throws IOException, XmlPullParserException {
- MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
+ ValidatingMetadataXpp3Reader mappingReader = new
ValidatingMetadataXpp3Reader();
Metadata metadata = null;
diff --git
a/maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/io/DefaultMetadataReader.java
b/maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/io/DefaultMetadataReader.java
index 9ecc7c6dac..f1ad14f522 100644
---
a/maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/io/DefaultMetadataReader.java
+++
b/maven-core/src/main/java/org/apache/maven/artifact/repository/metadata/io/DefaultMetadataReader.java
@@ -29,7 +29,7 @@
import java.util.Objects;
import org.apache.maven.artifact.repository.metadata.Metadata;
-import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
+import
org.apache.maven.repository.internal.metadata.ValidatingMetadataXpp3Reader;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@@ -54,7 +54,7 @@ public Metadata read(Reader input, Map<String, ?> options)
throws IOException {
Objects.requireNonNull(input, "input cannot be null");
try (Reader in = input) {
- return new MetadataXpp3Reader().read(in, isStrict(options));
+ return new ValidatingMetadataXpp3Reader().read(in,
isStrict(options));
} catch (XmlPullParserException e) {
throw new MetadataParseException(e.getMessage(),
e.getLineNumber(), e.getColumnNumber(), e);
}
@@ -64,7 +64,7 @@ public Metadata read(InputStream input, Map<String, ?>
options) throws IOExcepti
Objects.requireNonNull(input, "input cannot be null");
try (InputStream in = input) {
- return new MetadataXpp3Reader().read(in, isStrict(options));
+ return new ValidatingMetadataXpp3Reader().read(in,
isStrict(options));
} catch (XmlPullParserException e) {
throw new MetadataParseException(e.getMessage(),
e.getLineNumber(), e.getColumnNumber(), e);
}
diff --git
a/maven-core/src/main/java/org/apache/maven/internal/aether/MavenValidator.java
b/maven-core/src/main/java/org/apache/maven/internal/aether/MavenValidator.java
new file mode 100644
index 0000000000..4369d18a55
--- /dev/null
+++
b/maven-core/src/main/java/org/apache/maven/internal/aether/MavenValidator.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.internal.aether;
+
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.metadata.Metadata;
+import org.eclipse.aether.repository.LocalRepository;
+import org.eclipse.aether.spi.validator.Validator;
+import org.eclipse.aether.util.PathUtils;
+
+/**
+ * Simplest Maven specific validator that is meant to prevent un-interpolated
+ * elements enter resolver; if it does, is most likely some bug.
+ * <p>
+ * Note: {@link org.eclipse.aether.repository.RemoteRepository} is not
validated here,
+ * see <a href="https://github.com/apache/maven/issues/7398">GH-7398</a> for
details,
+ * and to keep very same behavior as Maven 3 did so far. If you want more,
upgrade to Maven 4 ;)
+ */
+public class MavenValidator implements Validator {
+ protected boolean containsPlaceholder(String value) {
+ return value != null && value.contains("${");
+ }
+
+ @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);
+ }
+
+ @Override
+ public void validateMetadata(Metadata metadata) throws
IllegalArgumentException {
+ if (containsPlaceholder(metadata.getGroupId())
+ || containsPlaceholder(metadata.getArtifactId())
+ || containsPlaceholder(metadata.getVersion())
+ || containsPlaceholder(metadata.getType())) {
+ throw new IllegalArgumentException("Not fully interpolated
metadata " + metadata);
+ }
+ PathUtils.validateMetadataComponents(metadata);
+ }
+
+ @Override
+ public void validateDependency(Dependency dependency) throws
IllegalArgumentException {
+ Artifact artifact = dependency.getArtifact();
+ if (containsPlaceholder(artifact.getGroupId())
+ || containsPlaceholder(artifact.getArtifactId())
+ || containsPlaceholder(artifact.getVersion())
+ || containsPlaceholder(artifact.getClassifier())
+ || containsPlaceholder(artifact.getExtension())
+ || containsPlaceholder(dependency.getScope())
+ || dependency.getExclusions().stream()
+ .anyMatch(e -> containsPlaceholder(e.getGroupId())
+ || containsPlaceholder(e.getArtifactId())
+ || containsPlaceholder(e.getClassifier())
+ || containsPlaceholder(e.getExtension()))) {
+ throw new IllegalArgumentException("Not fully interpolated
dependency " + dependency);
+ }
+ PathUtils.validateArtifactComponents(artifact);
+ }
+
+ @Override
+ public void validateLocalRepository(LocalRepository localRepository)
throws IllegalArgumentException {
+ if (containsPlaceholder(localRepository.getBasePath().toString())
+ || containsPlaceholder(localRepository.getContentType())
+ || containsPlaceholder(localRepository.getId())) {
+ throw new IllegalArgumentException("Not fully interpolated local
repository " + localRepository);
+ }
+ }
+}
diff --git
a/maven-core/src/main/java/org/apache/maven/internal/aether/MavenValidatorFactory.java
b/maven-core/src/main/java/org/apache/maven/internal/aether/MavenValidatorFactory.java
new file mode 100644
index 0000000000..83a48104c3
--- /dev/null
+++
b/maven-core/src/main/java/org/apache/maven/internal/aether/MavenValidatorFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.internal.aether;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.spi.validator.Validator;
+import org.eclipse.aether.spi.validator.ValidatorFactory;
+
+@Named
+@Singleton
+public class MavenValidatorFactory implements ValidatorFactory {
+ private final MavenValidator instance = new MavenValidator();
+
+ @Override
+ public Validator newInstance(RepositorySystemSession
repositorySystemSession) {
+ return instance;
+ }
+}
diff --git
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionRangeResolver.java
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionRangeResolver.java
index 23b7bc84b5..9542bece89 100644
---
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionRangeResolver.java
+++
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionRangeResolver.java
@@ -34,7 +34,7 @@
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.repository.metadata.Versioning;
-import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
+import
org.apache.maven.repository.internal.metadata.ValidatingMetadataXpp3Reader;
import org.eclipse.aether.RepositoryEvent;
import org.eclipse.aether.RepositoryEvent.EventType;
import org.eclipse.aether.RepositorySystemSession;
@@ -274,8 +274,9 @@ private Versioning readVersions(
if (metadata.getFile() != null &&
metadata.getFile().exists()) {
try (InputStream in = new
FileInputStream(metadata.getFile())) {
- versioning =
- new MetadataXpp3Reader().read(in,
false).getVersioning();
+ versioning = new ValidatingMetadataXpp3Reader()
+ .read(in, false)
+ .getVersioning();
}
}
}
diff --git
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionResolver.java
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionResolver.java
index cccbd9f5ff..b3b5fe70ca 100644
---
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionResolver.java
+++
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultVersionResolver.java
@@ -36,7 +36,7 @@
import org.apache.maven.artifact.repository.metadata.Snapshot;
import org.apache.maven.artifact.repository.metadata.SnapshotVersion;
import org.apache.maven.artifact.repository.metadata.Versioning;
-import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
+import
org.apache.maven.repository.internal.metadata.ValidatingMetadataXpp3Reader;
import org.codehaus.plexus.util.StringUtils;
import org.eclipse.aether.RepositoryCache;
import org.eclipse.aether.RepositoryEvent;
@@ -278,8 +278,9 @@ private Versioning readVersions(
if (metadata.getFile() != null &&
metadata.getFile().exists()) {
try (InputStream in = new
FileInputStream(metadata.getFile())) {
- versioning =
- new MetadataXpp3Reader().read(in,
false).getVersioning();
+ versioning = new ValidatingMetadataXpp3Reader()
+ .read(in, false)
+ .getVersioning();
/*
NOTE: Users occasionally misuse the id "local" for
remote repos which screws up the metadata
diff --git
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenMetadata.java
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenMetadata.java
index 6588b32fa5..12cc79bb08 100644
---
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenMetadata.java
+++
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenMetadata.java
@@ -28,8 +28,8 @@
import java.util.Map;
import org.apache.maven.artifact.repository.metadata.Metadata;
-import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
+import
org.apache.maven.repository.internal.metadata.ValidatingMetadataXpp3Reader;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@@ -99,7 +99,7 @@ static Metadata read(File metadataFile) throws
RepositoryException {
}
try (Reader reader = ReaderFactory.newXmlReader(metadataFile)) {
- return new MetadataXpp3Reader().read(reader, false);
+ return new ValidatingMetadataXpp3Reader().read(reader, false);
} catch (IOException e) {
throw new RepositoryException("Could not read metadata " +
metadataFile + ": " + e.getMessage(), e);
} catch (XmlPullParserException e) {
diff --git
a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/metadata/ValidatingMetadataXpp3Reader.java
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/metadata/ValidatingMetadataXpp3Reader.java
new file mode 100644
index 0000000000..338befe1be
--- /dev/null
+++
b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/metadata/ValidatingMetadataXpp3Reader.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.repository.internal.metadata;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.apache.maven.artifact.repository.metadata.Metadata;
+import org.apache.maven.artifact.repository.metadata.Versioning;
+import
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.eclipse.aether.util.PathUtils;
+
+/**
+ * Validating metadata reader.
+ *
+ * @since 3.10.0
+ */
+public final class ValidatingMetadataXpp3Reader {
+ private final MetadataXpp3Reader mr = new MetadataXpp3Reader();
+
+ /**
+ * Delegates to {@link MetadataXpp3Reader#read(Reader, boolean)}
+ */
+ public Metadata read(Reader reader, boolean strict) throws IOException,
XmlPullParserException {
+ return validate(mr.read(reader, strict));
+ }
+
+ /**
+ * Delegates to {@link MetadataXpp3Reader#read(InputStream, boolean)}
+ */
+ public Metadata read(InputStream in, boolean strict) throws IOException,
XmlPullParserException {
+ return validate(mr.read(in, strict));
+ }
+
+ /**
+ * Validates {@link Metadata}.
+ */
+ public static Metadata validate(Metadata metadata) {
+ if (metadata != null) {
+ PathUtils.validatePathComponent(metadata.getVersion(), "version");
+ Versioning versioning = metadata.getVersioning();
+ if (versioning != null) {
+ PathUtils.validatePathComponent(versioning.getLatest(),
"versioning/latest");
+ PathUtils.validatePathComponent(versioning.getRelease(),
"versioning/release");
+ for (int i = 0; i < versioning.getVersions().size(); i++) {
+
PathUtils.validatePathComponent(versioning.getVersions().get(i),
"versioning/versions[" + i + "]");
+ }
+ for (int i = 0; i < versioning.getSnapshotVersions().size();
i++) {
+ PathUtils.validatePathComponent(
+
versioning.getSnapshotVersions().get(i).getVersion(),
+ "versioning/snapshotVersions[" + i + "]/version");
+ }
+ }
+ }
+ return metadata;
+ }
+}
diff --git a/pom.xml b/pom.xml
index 07fd63400b..88367df3db 100644
--- a/pom.xml
+++ b/pom.xml
@@ -144,7 +144,7 @@ under the License.
<securityDispatcherVersion>2.0</securityDispatcherVersion>
<cipherVersion>2.0</cipherVersion>
<jxpathVersion>1.4.0</jxpathVersion>
- <resolverVersion>2.0.20</resolverVersion>
+ <resolverVersion>2.0.21-SNAPSHOT</resolverVersion>
<slf4jVersion>2.0.18</slf4jVersion>
<xmlunitVersion>2.12.0</xmlunitVersion>
<powermockVersion>2.0.9</powermockVersion>