From 0c560b22ce73323329645b836c9910abc257ce4e Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Tue, 25 Aug 2026 09:28:45 +0200 Subject: Secure library paths --- MediaBrowser.Controller/IO/FileSystemHelper.cs | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/IO/FileSystemHelper.cs b/MediaBrowser.Controller/IO/FileSystemHelper.cs index 44b7fadf5e..f636258191 100644 --- a/MediaBrowser.Controller/IO/FileSystemHelper.cs +++ b/MediaBrowser.Controller/IO/FileSystemHelper.cs @@ -166,4 +166,35 @@ public static class FileSystemHelper return ResolveLinkTarget(fileInfo.FullName, returnFinalTarget); } + + /// + /// Combines a caller supplied name with a parent directory, making sure the name cannot escape that directory. + /// + /// The directory the name has to resolve inside of. + /// The name of the child. + /// + /// The full path of the child, or null if is not the name of a direct child + /// of . + /// + 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; + } } -- cgit v1.2.3