You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/08/31 12:02:44 UTC

(maven-deploy-plugin) 03/04: fix: f015 (LOW) — The guard now compares locations: isSameLocation() resolves both sides t

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch security/audit-docs-minor
in repository https://gitbox.apache.org/repos/asf/maven-deploy-plugin.git

commit 3ecf5558a83400122155bc9f78914b7110327ac6
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Mon Aug 31 14:01:35 2026 +0200

    fix: f015 (LOW) — The guard now compares locations: isSameLocation() resolves both sides t
    
    Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---
 .../java/org/apache/maven/plugins/deploy/DeployFileMojo.java | 12 +++++++++++-
 .../apache/maven/plugins/deploy/DeployFileMojoUnitTest.java  | 12 ++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/maven/plugins/deploy/DeployFileMojo.java b/src/main/java/org/apache/maven/plugins/deploy/DeployFileMojo.java
index 47603a1..e9a14c6 100644
--- a/src/main/java/org/apache/maven/plugins/deploy/DeployFileMojo.java
+++ b/src/main/java/org/apache/maven/plugins/deploy/DeployFileMojo.java
@@ -357,7 +357,7 @@ public class DeployFileMojo extends AbstractDeployMojo {
         ProducedArtifact artifact = session.createProducedArtifact(
                 groupId, artifactId, version, classifier, isFilePom ? "pom" : getExtension(file), packaging);
 
-        if (file.equals(getLocalRepositoryFile(artifact))) {
+        if (isSameLocation(file, getLocalRepositoryFile(artifact))) {
             throw new MojoException("Cannot deploy artifact from the local repository: " + file);
         }
 
@@ -544,6 +544,16 @@ public class DeployFileMojo extends AbstractDeployMojo {
         return session.getPathForLocalArtifact(artifact);
     }
 
+    /**
+     * Compares two paths as locations rather than spellings: a textual {@code Path.equals} lets a
+     * relative path, a symlink, or any non-canonical spelling of the same file slip past the
+     * local-repository self-deploy guard (an anti-footgun against local-repo metadata corruption,
+     * not a security boundary - but it should at least hold against trivial re-spellings).
+     */
+    static boolean isSameLocation(Path a, Path b) {
+        return realOrNormalized(a).equals(realOrNormalized(b));
+    }
+
     /**
      * Process the supplied pomFile to get groupId, artifactId, version, and packaging
      *
diff --git a/src/test/java/org/apache/maven/plugins/deploy/DeployFileMojoUnitTest.java b/src/test/java/org/apache/maven/plugins/deploy/DeployFileMojoUnitTest.java
index c6292fc..50e0e1d 100644
--- a/src/test/java/org/apache/maven/plugins/deploy/DeployFileMojoUnitTest.java
+++ b/src/test/java/org/apache/maven/plugins/deploy/DeployFileMojoUnitTest.java
@@ -228,6 +228,18 @@ class DeployFileMojoUnitTest {
         Mockito.verify(mojo.logger).warn(Mockito.contains("Could not read a POM from"));
     }
 
+    @Test
+    void selfDeployGuardComparesLocationsNotSpellings() throws Exception {
+        Path dir = java.nio.file.Files.createTempDirectory("deploy-file-test");
+        Path real = java.nio.file.Files.createFile(dir.resolve("artifact.jar"));
+
+        assertTrue(DeployFileMojo.isSameLocation(real, real));
+        assertTrue(DeployFileMojo.isSameLocation(real, dir.resolve("sub/../artifact.jar")));
+        Path link = java.nio.file.Files.createSymbolicLink(dir.resolve("link.jar"), real);
+        assertTrue(DeployFileMojo.isSameLocation(link, real));
+        assertFalse(DeployFileMojo.isSameLocation(real, dir.resolve("other.jar")));
+    }
+
     private static Path createJar(String name, String... entries) throws java.io.IOException {
         Path dir = java.nio.file.Files.createTempDirectory("deploy-file-test");
         Path jar = dir.resolve(name);