Skip to content

Commit dfef37c

Browse files
authored
Merge pull request jenkinsci#159 from dwnusbaum/security-fix-test-compatibility
Fix recent security fixes if JENKINS_HOME is a symlink and failing tests on Windows after recent security fixes
2 parents 71c3f0a + 6355e5d commit dfef37c

File tree

2 files changed

+13
-4
lines changed

2 files changed

+13
-4
lines changed

src/main/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStep.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ private static boolean isDescendant(FilePath child, FilePath parent) throws IOEx
248248
if (child.isRemote() || parent.isRemote()) {
249249
throw new IllegalStateException();
250250
}
251-
return new File(child.getRemote()).getCanonicalFile().toPath().startsWith(parent.absolutize().getRemote());
251+
return new File(child.getRemote()).getCanonicalFile().toPath().startsWith(new File(parent.getRemote()).getCanonicalPath());
252252
}
253253

254254
private static final long serialVersionUID = 1L;

src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStepTest.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,13 @@ public void pathTraversalRejected() throws Exception {
232232

233233
WorkflowRun b = p.getLastBuild();
234234
assertEquals(1, b.getNumber());
235-
r.assertLogContains("secrets/master.key references a file that is not inside " + r.jenkins.getWorkspaceFor(p).getRemote(), b);
235+
r.assertLogContains("master.key references a file that is not inside " + r.jenkins.getWorkspaceFor(p).getRemote(), b);
236236
}
237237

238238
@Issue("SECURITY-2491")
239239
@Test
240240
public void symlinksInReadTrustedCannotEscapeWorkspaceContext() throws Exception {
241+
assumeFalse(Functions.isWindows()); // On Windows, the symlink is treated as a regular file, so there is no vulnerability, but the behavior is different.
241242
SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true;
242243
sampleRepo.init();
243244
sampleRepo.write("Jenkinsfile", "node { checkout scm; echo \"${readTrusted 'secrets/master.key'}\"}");
@@ -259,6 +260,7 @@ public void symlinksInReadTrustedCannotEscapeWorkspaceContext() throws Exception
259260
@Issue("SECURITY-2491")
260261
@Test
261262
public void symlinksInUntrustedRevisionCannotEscapeWorkspace() throws Exception {
263+
assumeFalse(Functions.isWindows()); // On Windows, the symlink is treated as a regular file, so there is no vulnerability, but the behavior is different.
262264
SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true;
263265
sampleRepo.init();
264266
sampleRepo.write("Jenkinsfile", "node { checkout scm; echo \"${readTrusted 'secrets/master.key'}\"}");
@@ -286,6 +288,7 @@ public void symlinksInUntrustedRevisionCannotEscapeWorkspace() throws Exception
286288
@Issue("SECURITY-2491")
287289
@Test
288290
public void symlinksInNonMultibranchCannotEscapeWorkspaceContextViaReadTrusted() throws Exception {
291+
assumeFalse(Functions.isWindows()); // On Windows, the symlink is treated as a regular file, so there is no vulnerability, but the behavior is different.
289292
SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true;
290293
sampleRepo.init();
291294
sampleRepo.write("Jenkinsfile", "echo \"${readTrusted 'master.key'}\"");
@@ -319,7 +322,10 @@ public void symlinksInNonMultibranchCannotEscapeWorkspaceContextViaReadTrusted()
319322
FileUtils.copyDirectory(new File(sampleRepo.getRoot(), ".git"), gitDirInSvnRepo);
320323
String jenkinsRootDir = r.jenkins.getRootDir().toString();
321324
// Add a Git post-checkout hook to the .git folder in the SVN repo.
322-
Files.write(gitDirInSvnRepo.toPath().resolve("hooks/post-checkout"), ("#!/bin/sh\ntouch '" + jenkinsRootDir + "/hook-executed'\n").getBytes(StandardCharsets.UTF_8));
325+
Path postCheckoutHook = gitDirInSvnRepo.toPath().resolve("hooks/post-checkout");
326+
// Always create hooks directory for compatibility with https://github.com/jenkinsci/git-plugin/pull/1207.
327+
Files.createDirectories(postCheckoutHook.getParent());
328+
Files.write(postCheckoutHook, ("#!/bin/sh\ntouch '" + jenkinsRootDir + "/hook-executed'\n").getBytes(StandardCharsets.UTF_8));
323329
sampleRepoSvn.svnkit("add", sampleRepoSvn.wc() + "/Jenkinsfile");
324330
sampleRepoSvn.svnkit("add", sampleRepoSvn.wc() + "/.git");
325331
sampleRepoSvn.svnkit("propset", "svn:executable", "ON", sampleRepoSvn.wc() + "/.git/hooks/post-checkout");
@@ -354,7 +360,10 @@ public void symlinksInNonMultibranchCannotEscapeWorkspaceContextViaReadTrusted()
354360
FileUtils.copyDirectory(new File(sampleRepo.getRoot(), ".git"), gitDirInSvnRepo);
355361
String jenkinsRootDir = r.jenkins.getRootDir().toString();
356362
// Add a Git post-checkout hook to the .git folder in the SVN repo.
357-
Files.write(gitDirInSvnRepo.toPath().resolve("hooks/post-checkout"), ("#!/bin/sh\ntouch '" + jenkinsRootDir + "/hook-executed'\n").getBytes(StandardCharsets.UTF_8));
363+
Path postCheckoutHook = gitDirInSvnRepo.toPath().resolve("hooks/post-checkout");
364+
// Always create hooks directory for compatibility with https://github.com/jenkinsci/git-plugin/pull/1207.
365+
Files.createDirectories(postCheckoutHook.getParent());
366+
Files.write(postCheckoutHook, ("#!/bin/sh\ntouch '" + jenkinsRootDir + "/hook-executed'\n").getBytes(StandardCharsets.UTF_8));
358367
sampleRepoSvn.svnkit("add", sampleRepoSvn.wc() + "/Jenkinsfile");
359368
sampleRepoSvn.svnkit("add", sampleRepoSvn.wc() + "/.git");
360369
sampleRepoSvn.svnkit("propset", "svn:executable", "ON", sampleRepoSvn.wc() + "/.git/hooks/post-checkout");

0 commit comments

Comments
 (0)