== How to fix it in Java I/O API === Code examples :code_impact: delete include::../../common/fix/code-rationale.adoc[] ==== Noncompliant code example [source,java,diff-id=1,diff-type=noncompliant] ---- @Controller public class ExampleController { static private String targetDirectory = "/path/to/target/directory/"; @GetMapping(value = "/delete") public void delete(@RequestParam("filename") String filename) throws IOException { File file = new File(targetDirectory + filename); file.delete(); } } ---- ==== Compliant solution [source,java,diff-id=1,diff-type=compliant] ---- @Controller public class ExampleController { private static String targetDirectory = "/path/to/target/directory/"; private static Path targetPath = new File(targetDirectory).toPath().normalize(); @GetMapping(value = "/delete") public void delete(@RequestParam("filename") String filename) throws IOException { File file = new File(targetPath + filename); if (!file.toPath().normalize().startsWith(targetPath)) { throw new IOException("Entry is outside of the target directory"); } file.delete(); } } ---- === How does this work? :canonicalization_function: java.io.File.getCanonicalPath include::../../common/fix/self-validation.adoc[] === Pitfalls include::../../common/pitfalls/partial-path-traversal.adoc[] For example, the following code is vulnerable to partial path injection. Note that the string `targetDirectory` does not end with a path separator: [source, java] ---- static private String targetDirectory = "/Users/John"; @GetMapping(value = "/endpoint") public void endpoint(@RequestParam("folder") File fileName) throws IOException { String canonicalizedFileName = fileName.getCanonicalPath(); if (!canonicalizedFileName .startsWith(targetDirectory)) { throw new IOException("Entry is outside of the target directory"); } } ---- This check can be bypassed because `"/Users/Johnny".startsWith("/Users/John")` returns `true`. Thus, for validation, `"/Users/John"` should actually be `"/Users/John/"`. **Warning**: Some functions, such as `.getCanonicalPath`, remove the terminating path separator in their return value. + The validation code should be tested to ensure that it cannot be impacted by this issue. https://github.com/aws/aws-sdk-java/security/advisories/GHSA-c28r-hw5m-5gv3[Here is a real-life example of this vulnerability.] :joining_docs: https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html :joining_func: java.nio.file.Path.resolve include::../../common/pitfalls/oob-specific-path-joining.adoc[]