Secure library paths

This commit is contained in:
Shadowghost
2026-08-25 09:28:45 +02:00
parent d6bcad3b59
commit 0c560b22ce
5 changed files with 165 additions and 10 deletions
@@ -166,4 +166,35 @@ public static class FileSystemHelper
return ResolveLinkTarget(fileInfo.FullName, returnFinalTarget);
}
/// <summary>
/// Combines a caller supplied name with a parent directory, making sure the name cannot escape that directory.
/// </summary>
/// <param name="parentPath">The directory the name has to resolve inside of.</param>
/// <param name="name">The name of the child.</param>
/// <returns>
/// The full path of the child, or <c>null</c> if <paramref name="name"/> is not the name of a direct child
/// of <paramref name="parentPath"/>.
/// </returns>
public static string? GetChildPath(string parentPath, string name)
{
if (string.IsNullOrWhiteSpace(name) || name.Contains('\0', StringComparison.Ordinal))
{
return null;
}
// Rejects directory separators, and on Windows also volume separators, as those make the name more than a single segment.
if (!string.Equals(Path.GetFileName(name), name, StringComparison.Ordinal))
{
return null;
}
var fullPath = Path.GetFullPath(Path.Combine(parentPath, name));
var fullParentPath = Path.TrimEndingDirectorySeparator(Path.GetFullPath(parentPath));
// Catches the remaining relative names, "." and "..", which are valid single segments.
return string.Equals(Path.GetDirectoryName(fullPath), fullParentPath, StringComparison.Ordinal)
? fullPath
: null;
}
}