diff --git a/dotnet/test/DotNetUnitTest/FileIO/FileIOTests.cs b/dotnet/test/DotNetUnitTest/FileIO/FileIOTests.cs index 916c6a895..a547c8089 100644 --- a/dotnet/test/DotNetUnitTest/FileIO/FileIOTests.cs +++ b/dotnet/test/DotNetUnitTest/FileIO/FileIOTests.cs @@ -91,20 +91,21 @@ public void GXDBFilePathTest() "content%5c..%5c..%5c..%5cdocument.aspx","content%255c%252e%252e%255c%252e%252e%255c%252e%252e%255cdocument.aspx","content%255c..%255c..%255c..%255cdocument.aspx", "content%c0%af..%c0%af..%c0%af..%c0%afdocument.aspx","content%c1%9c..%c1%9c..%c1%9c..%c1%9cdocument.aspx"}; + string safeResolved = GXDbFile.ResolveUri($"{GXDbFile.Scheme}:safe.txt", false); + string safeResolvedPath = Uri.TryCreate(safeResolved, UriKind.Absolute, out Uri safeUri) && safeUri.IsFile + ? safeUri.LocalPath + : safeResolved; + string fullBase = Path.GetDirectoryName(Path.GetFullPath(safeResolvedPath)) + Path.DirectorySeparatorChar; + foreach (string fileName in filesName) { string newFileName = GXDbFile.ResolveUri($"{GXDbFile.Scheme}:{fileName}", false); - string baseDir = Preferences.getBLOB_PATH(); - try - { - bool isOK = new Uri(newFileName).LocalPath.StartsWith(Path.GetFullPath(baseDir), StringComparison.OrdinalIgnoreCase); - Assert.True(isOK); - } - catch (Exception ex) - { - - Assert.True(false, $"FileName:{newFileName} Error:{ex.Message} ExternalProvider:{ServiceFactory.GetExternalProvider()?.GetType().FullName} fileName:{fileName}"); - } + string resolvedPath = Uri.TryCreate(newFileName, UriKind.Absolute, out Uri parsedUri) && parsedUri.IsFile + ? parsedUri.LocalPath + : newFileName; + string fullResolved = Path.GetFullPath(resolvedPath); + bool isOK = fullResolved.StartsWith(fullBase, StringComparison.OrdinalIgnoreCase); + Assert.True(isOK, $"Path traversal detected: resolved '{fullResolved}' is outside base '{fullBase}' for input '{fileName}'"); } }