diff --git a/src/main/java/hudson/plugins/repo/RepoScm.java b/src/main/java/hudson/plugins/repo/RepoScm.java index b9630a6..22ed936 100644 --- a/src/main/java/hudson/plugins/repo/RepoScm.java +++ b/src/main/java/hudson/plugins/repo/RepoScm.java @@ -31,6 +31,7 @@ import java.net.URL; import java.nio.charset.Charset; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -950,10 +951,13 @@ public void checkout( build.addAction(manifestAction); } - private void abortIfUrlLocal() throws AbortException { - if (StringUtils.isNotEmpty(manifestRepositoryUrl) - && (manifestRepositoryUrl.toLowerCase(Locale.ENGLISH).startsWith("file://") - || Files.exists(Paths.get(manifestRepositoryUrl)))) { + /** + * Throws an {@link AbortException} if {@link #manifestRepositoryUrl} references a local file. + * + * @throws AbortException if {@link #manifestRepositoryUrl} references a local file + */ + void abortIfUrlLocal() throws AbortException { + if (!isValidRepositoryUrl(manifestRepositoryUrl)) { throw new AbortException("Checkout of Repo url '" + manifestRepositoryUrl + "' aborted because it references a local directory, " + "which may be insecure. " @@ -962,6 +966,20 @@ private void abortIfUrlLocal() throws AbortException { } } + private static boolean isValidRepositoryUrl(final String url) { + if (StringUtils.isEmpty(url)) { + return true; + } else if (url.toLowerCase(Locale.ENGLISH).startsWith("file://")) { + return false; + } + try { + // Check for local URLs with no protocol like /path/to/repo + return !Files.exists(Paths.get(url)); + } catch (InvalidPathException e) { + return true; + } + } + private int doSync(final Launcher launcher, @Nonnull final FilePath workspace, final OutputStream logger, final EnvVars env) throws IOException, InterruptedException { diff --git a/src/test/java/hudson/plugins/repo/RepoScmTest.java b/src/test/java/hudson/plugins/repo/RepoScmTest.java index 88527aa..2496a6c 100644 --- a/src/test/java/hudson/plugins/repo/RepoScmTest.java +++ b/src/test/java/hudson/plugins/repo/RepoScmTest.java @@ -1,13 +1,16 @@ package hudson.plugins.repo; +import hudson.AbortException; import hudson.model.FreeStyleProject; import hudson.tasks.Shell; import org.junit.Rule; import org.junit.Test; +import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * {@link JenkinsRule} based tests for {@link RepoScm} @@ -31,4 +34,15 @@ public void configRoundTrip() throws Exception { assertTrue(scm.isCleanFirst()); assertEquals(manifestRepositoryUrl, scm.getManifestRepositoryUrl()); } + + @Issue("JENKINS-68562") + @Test + public void abortIfUrlLocal() throws Exception { + final String manifestRepositoryUrl = "https://gerrit/projects/platform.git"; + try { + new RepoScm(manifestRepositoryUrl).abortIfUrlLocal(); + } catch (AbortException e) { + fail("https manifest URLs should always be valid"); + } + } }