diff --git a/api/src/org/labkey/api/pipeline/PipeRoot.java b/api/src/org/labkey/api/pipeline/PipeRoot.java index d71491f9586..850cc631b81 100644 --- a/api/src/org/labkey/api/pipeline/PipeRoot.java +++ b/api/src/org/labkey/api/pipeline/PipeRoot.java @@ -71,22 +71,22 @@ public interface PipeRoot extends SecurableResource Path resolveToNioPathFromUrl(String url); /** - * @return the file that's at the given relativePath from the pipeline root. Will be null if the relative path - * attempts to reference something that's not under the root (such as "../../etc/passwd". When the root + * @return the file that's at the given relativePath from the pipeline root. When the root * is configured with an alternative file path, we'll check to see if the file exists there. If not, we'll return * a path relative to the root's primary path. + * @throws org.labkey.api.util.FileUtil.InvalidPathReferenceException if the relative path + * attempts to reference something not under the root (such as "../../etc/passwd") */ @Deprecated // prefer resolvePathToFileLike() - @Nullable File resolvePath(String relativePath); /** - * @return the file that's at the given relativePath from the pipeline root. Will be null if the relative path - * attempts to reference something that's not under the root (such as "../../etc/passwd". When the root + * @return the file that's at the given relativePath from the pipeline root. When the root * is configured with an alternative file path, we'll check to see if the file exists there. If not, we'll return * a path relative to the root's primary path. + * @throws org.labkey.api.util.FileUtil.InvalidPathReferenceException if the relative path + * attempts to reference something not under the root (such as "../../etc/passwd") */ - @Nullable FileLike resolvePathToFileLike(String relativePath); /** diff --git a/api/src/org/labkey/api/util/ExceptionUtil.java b/api/src/org/labkey/api/util/ExceptionUtil.java index 6c623fe76c6..3649564a0ba 100644 --- a/api/src/org/labkey/api/util/ExceptionUtil.java +++ b/api/src/org/labkey/api/util/ExceptionUtil.java @@ -865,6 +865,21 @@ else if (ex instanceof BadRequestException) message = ex.getMessage(); unhandledException = null; } + else if (ex instanceof FileUtil.InvalidPathReferenceException ipre) + { + responseStatus = HttpServletResponse.SC_NOT_FOUND; + errorType = ErrorRenderer.ErrorType.notFound; + if (ex.getMessage() != null) + { + message = ex.getMessage(); + responseStatusMessage = message; + } + else + message = responseStatus + ": Page not Found"; + unhandledException = null; + log.info("InvalidPathReferenceException: {}", ipre.getInput()); + log.debug("InvalidPathReferenceException", ex); + } else if (ex instanceof NotFoundException) { responseStatus = HttpServletResponse.SC_NOT_FOUND; diff --git a/api/src/org/labkey/api/util/FileUtil.java b/api/src/org/labkey/api/util/FileUtil.java index d7675c3092d..d61983e5142 100644 --- a/api/src/org/labkey/api/util/FileUtil.java +++ b/api/src/org/labkey/api/util/FileUtil.java @@ -826,11 +826,20 @@ public static File appendPath(File dir, org.labkey.api.util.Path originalPath) { org.labkey.api.util.Path path = originalPath.normalize(); if (path == null || (!path.isEmpty() && "..".equals(path.get(0)))) - throw new InvalidPathException(originalPath.toString(), "Path to parent not allowed"); + throw new InvalidPathReferenceException(originalPath.toString(), "Path to parent not allowed"); @SuppressWarnings("SSBasedInspection") var ret = new File(dir, path.toString()); - if (!ret.toPath().normalize().startsWith(dir.toPath().normalize())) - throw new InvalidPathException(originalPath.toString(), "Path to parent not allowed"); + boolean valid; + try + { + valid = ret.toPath().normalize().startsWith(dir.toPath().normalize()); + } + catch (InvalidPathException e) + { + throw new InvalidPathReferenceException(originalPath.toString(), e.getMessage()); + } + if (!valid) + throw new InvalidPathReferenceException(originalPath.toString(), "Path to parent not allowed"); return ret; } @@ -840,7 +849,7 @@ public static FileLike appendPath(FileLike dir, org.labkey.api.util.Path path) { path = path.normalize(); if (!path.isEmpty() && "..".equals(path.get(0))) - throw new InvalidPathException(path.toString(), "Path to parent not allowed"); + throw new InvalidPathReferenceException(path.toString(), "Path to parent not allowed"); return dir.resolveFile(path); } @@ -871,7 +880,7 @@ public static File appendName(File dir, String name) var ret = new File(dir, name); if (!ret.toPath().normalize().startsWith(dir.toPath().normalize())) - throw new InvalidPathException(name, "Path to parent not allowed"); + throw new InvalidPathReferenceException(name, "Path to parent not allowed"); return ret; } @@ -882,7 +891,7 @@ public static Path appendName(Path dir, String name) var ret = dir.resolve(name); if (!ret.normalize().startsWith(dir.normalize())) - throw new InvalidPathException(name, "Path to parent not allowed"); + throw new InvalidPathReferenceException(name, "Path to parent not allowed"); return ret; } @@ -893,11 +902,24 @@ public static void legalPathPartThrow(String name) { int invalidCharacterIndex = StringUtils.indexOfAny(name, '/', File.separatorChar); if (invalidCharacterIndex >= 0) - throw new InvalidPathException(name, "Invalid file or directory name", invalidCharacterIndex); + throw new InvalidPathReferenceException(name, "Invalid file or directory name", invalidCharacterIndex); if (".".equals(name) || "..".equals(name)) - throw new InvalidPathException(name, "Invalid file or directory name"); + throw new InvalidPathReferenceException(name, "Invalid file or directory name"); } + /** Our own subclass for bogus paths that we can special-case in ExceptionUtil in terms of HTTP response codes and logging */ + public static class InvalidPathReferenceException extends InvalidPathException + { + public InvalidPathReferenceException(String path, String reason) + { + super(path, reason); + } + + public InvalidPathReferenceException(String name, String reason, int index) + { + super(name, reason, index); + } + } public static String decodeSpaces(@NotNull String str) { diff --git a/pipeline/src/org/labkey/pipeline/api/PipeRootImpl.java b/pipeline/src/org/labkey/pipeline/api/PipeRootImpl.java index 51af9631832..b9069d2fd11 100644 --- a/pipeline/src/org/labkey/pipeline/api/PipeRootImpl.java +++ b/pipeline/src/org/labkey/pipeline/api/PipeRootImpl.java @@ -359,7 +359,6 @@ private Path findRootPath(Path file) @Override - @Nullable public File resolvePath(String pathStr) { if (null == pathStr) @@ -370,7 +369,7 @@ public File resolvePath(String pathStr) @Nullable - public File resolvePath(org.labkey.api.util.Path path) + private File resolvePath(org.labkey.api.util.Path path) { var pair = _resolveRoot(path); if (null == pair) @@ -380,8 +379,11 @@ public File resolvePath(org.labkey.api.util.Path path) @Override - public @Nullable FileLike resolvePathToFileLike(String relativePath) + public FileLike resolvePathToFileLike(String relativePath) { + if (null == relativePath) + throw new FileUtil.InvalidPathReferenceException(null, "Must specify a file path"); + var parsedPath = org.labkey.api.util.Path.parse(relativePath); var pair = _resolveRoot(parsedPath);