=== How to fix it in .NET :canonicalization_function1: System.IO.Path.GetFullPath :canonicalization_function2: System.IO.Path.GetFileName include::../../common/fix/code-rationale.adoc[] ==== Noncompliant code example [source,csharp,diff-id=1,diff-type=noncompliant] ---- public class ExampleController : Controller { private static string TargetDirectory = "/example/directory/"; public void ExtractEntry(IEnumerator entriesEnumerator) { ZipArchiveEntry entry = entriesEnumerator.Current; string destinationPath = Path.Combine(TargetDirectory, entry.FullName); entry.ExtractToFile(destinationPath); } } ---- ==== Compliant solution [source,csharp,diff-id=1,diff-type=compliant] ---- public class ExampleController : Controller { private static string TargetDirectory = "/example/directory/"; public void ExtractEntry(IEnumerator entriesEnumerator) { ZipArchiveEntry entry = entriesEnumerator.Current; string destinationPath = Path.Combine(TargetDirectory, entry.FullName); string canonicalDestinationPath = Path.GetFullPath(destinationPath); if (canonicalDestinationPath.StartsWith(TargetDirectory, StringComparison.Ordinal)) { entry.ExtractToFile(canonicalDestinationPath); } } } ---- === How does this work? include::../../common/fix/how-does-this-work.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, csharp] ---- static private String TargetDirectory = "/Users/John"; public void ExtractEntry(IEnumerator entriesEnumerator) { ZipArchiveEntry entry = entriesEnumerator.Current; string canonicalDestinationPath = Path.GetFullPath(TargetDirectory); if (canonicalDestinationPath.StartsWith(TargetDirectory, StringComparison.Ordinal)) { entry.ExtractToFile(canonicalDestinationPath); } } ---- 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 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.]