Are there any standard library methods that can filter out paths which include special traversal sequences, such as ../
and all other convoluted forms of upwards directory traversal, to safeguard a file path API input from traversing upwards of a given "root" path?
I have a class that contains a root folder value member, and a member function that accepts paths to recursively delete. My goal is to make this API safe, in filtering out any input path provided to it - which would translate to a path upwards of the root folder value. The aim is that this class would be liberally used to delete files under the root path, but it would never touch anything upwards of the root path.
This is similar to the broader path traversal attack.
Methods that are too restrictive (i.e. may result in false negatives) may be fine for my specific use case, if this simplifies things, and also, my current needs are for file system paths not web ones (although, a web module for the equivalent sake might theoretically work here).
You can use
Path.normalize()
to strip out ".." elements (and their preceding elements) from a path — e.g. it'll turn "a/b/../c" into "a/c". Note that it won't strip out a ".." at the beginning of a path, since there's no preceding directory component for it to remove as well. So if you're going to prepend another path, do that first, then normalize the result.You can also use
Path.startsWith(Path)
to check whether one path is a descendant of another. AndPath.isAbsolute()
tells you, unsurprisingly, whether a path is absolute or relative.Here's how I'd process the untrusted paths coming into the API:
You do not need to use a third-party library to do this. The file APIs that Java provides give you the ability to verify that a file is a descendent of another.
Path.resolve(String) will resolve parent directory references, absolute, and relative paths. If an absolute path is passed as an argument to the resolve method it returns the absolute path. It does not guarantee that the returned value is a descendent of the path the method was invoked on.
You can check that a path is a descendent of another path by using the Path.startsWith(Path) method.
When
pathAsString
contains references to parent directories or was an absolute path,relative
can reference a file that is not contained inroot
. When this is the case you can throw an exception before any modifications to the file are permitted.