diff --git a/src/main/java/hudson/plugins/git/GitSCM.java b/src/main/java/hudson/plugins/git/GitSCM.java index c8fbe43190..cfb6417d40 100644 --- a/src/main/java/hudson/plugins/git/GitSCM.java +++ b/src/main/java/hudson/plugins/git/GitSCM.java @@ -78,6 +78,7 @@ import java.io.Serializable; import java.io.Writer; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Paths; import java.text.MessageFormat; import java.util.AbstractList; @@ -1393,10 +1394,11 @@ public void checkout(Run build, Launcher launcher, FilePath workspace, Tas } } - private void abortIfSourceIsLocal() throws AbortException { + /* Package protected for test access */ + void abortIfSourceIsLocal() throws AbortException { for (UserRemoteConfig userRemoteConfig: getUserRemoteConfigs()) { String remoteUrl = userRemoteConfig.getUrl(); - if (remoteUrl != null && (remoteUrl.toLowerCase(Locale.ENGLISH).startsWith("file://") || Files.exists(Paths.get(remoteUrl)))) { + if (!isRemoteUrlValid(remoteUrl)) { throw new AbortException("Checkout of Git remote '" + remoteUrl + "' aborted because it references a local directory, " + "which may be insecure. You can allow local checkouts anyway by setting the system property '" + ALLOW_LOCAL_CHECKOUT_PROPERTY + "' to true."); @@ -1404,6 +1406,20 @@ private void abortIfSourceIsLocal() throws AbortException { } } + private static boolean isRemoteUrlValid(String remoteUrl) { + if (remoteUrl == null) { + return true; + } else if (remoteUrl.toLowerCase(Locale.ENGLISH).startsWith("file://")) { + return false; + } + try { + // Check for local remotes with no protocol like /path/to/repo.git/ + return !Files.exists(Paths.get(remoteUrl)); + } catch (InvalidPathException e) { + return true; + } + } + private void printCommitMessageToLog(TaskListener listener, GitClient git, final Build revToBuild) throws IOException { try { diff --git a/src/test/java/hudson/plugins/git/GitSCMUnitTest.java b/src/test/java/hudson/plugins/git/GitSCMUnitTest.java index d7ee0fa034..a0ea98cdda 100644 --- a/src/test/java/hudson/plugins/git/GitSCMUnitTest.java +++ b/src/test/java/hudson/plugins/git/GitSCMUnitTest.java @@ -23,6 +23,7 @@ */ package hudson.plugins.git; +import hudson.AbortException; import hudson.EnvVars; import static hudson.plugins.git.GitSCM.createRepoList; import hudson.plugins.git.browser.GitRepositoryBrowser; @@ -43,6 +44,8 @@ import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import org.jvnet.hudson.test.Issue; import static org.hamcrest.MatcherAssert.*; import static org.hamcrest.Matchers.*; @@ -338,4 +341,17 @@ public void testSetDoGenerateSubmoduleConfigurations() { /* Confirms the passed value `true` is ignored */ assertFalse(gitSCM.getDoGenerateSubmoduleConfigurations()); } + + @Issue("JENKINS-68562") + @Test + public void testAbortIfSourceIsLocal() { + GitSCM gitSCM = new GitSCM(createRepoList(repoURL, null), + Collections.singletonList(new BranchSpec("master")), + null, null, Collections.emptyList()); + try { + gitSCM.abortIfSourceIsLocal(); + } catch (AbortException e) { + fail("https remote URLs should always be valid"); + } + } }