From 53be8b112ba51c2433af2fa2dfd9ea8bfec59114 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Fri, 30 Nov 2018 08:11:26 +0100 Subject: [PATCH] avoid path traversal attack --- .../InitialRepositoryLocationResolver.java | 8 ++++++++ .../InitialRepositoryLocationResolverTest.java | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/scm-core/src/main/java/sonia/scm/repository/InitialRepositoryLocationResolver.java b/scm-core/src/main/java/sonia/scm/repository/InitialRepositoryLocationResolver.java index 54ef8875b0..09fc66b87e 100644 --- a/scm-core/src/main/java/sonia/scm/repository/InitialRepositoryLocationResolver.java +++ b/scm-core/src/main/java/sonia/scm/repository/InitialRepositoryLocationResolver.java @@ -1,8 +1,12 @@ package sonia.scm.repository; +import com.google.common.base.CharMatcher; + import java.nio.file.Path; import java.nio.file.Paths; +import static com.google.common.base.Preconditions.checkArgument; + /** * A Location Resolver for File based Repository Storage. *

@@ -19,6 +23,8 @@ public class InitialRepositoryLocationResolver { private static final String DEFAULT_REPOSITORY_PATH = "repositories"; + private static final CharMatcher ID_MATCHER = CharMatcher.anyOf("/\\"); + /** * Returns the initial path to repository. * @@ -27,6 +33,8 @@ public class InitialRepositoryLocationResolver { * @return initial path of repository */ public Path getPath(String repositoryId) { + // avoid path traversal attacks + checkArgument(ID_MATCHER.matchesNoneOf(repositoryId), "repository id contains invalid characters"); return Paths.get(DEFAULT_REPOSITORY_PATH, repositoryId); } diff --git a/scm-core/src/test/java/sonia/scm/repository/InitialRepositoryLocationResolverTest.java b/scm-core/src/test/java/sonia/scm/repository/InitialRepositoryLocationResolverTest.java index 9af00ce183..9411f92ff6 100644 --- a/scm-core/src/test/java/sonia/scm/repository/InitialRepositoryLocationResolverTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/InitialRepositoryLocationResolverTest.java @@ -1,5 +1,6 @@ package sonia.scm.repository; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; @@ -20,4 +21,20 @@ class InitialRepositoryLocationResolverTest { assertThat(path).isRelative(); assertThat(path.toString()).isEqualTo("repositories" + File.separator + "42"); } + + @Test + void shouldThrowIllegalArgumentExceptionIfIdHasASlash() { + InitialRepositoryLocationResolver resolver = new InitialRepositoryLocationResolver(); + Assertions.assertThrows(IllegalArgumentException.class, () -> { + resolver.getPath("../../../passwd"); + }); + } + + @Test + void shouldThrowIllegalArgumentExceptionIfIdHasABackSlash() { + InitialRepositoryLocationResolver resolver = new InitialRepositoryLocationResolver(); + Assertions.assertThrows(IllegalArgumentException.class, () -> { + resolver.getPath("..\\..\\..\\users.ntlm"); + }); + } }