Skip to content

Commit 6eee1c2

Browse files
committed
Security: Fix double-encoding path traversal vulnerability
- Recursively decode URL-encoded paths to catch %252e%252e attacks - Reject any remaining % characters after full decoding - Prevents bypass of path traversal protection via encoding tricks
1 parent 244ca0f commit 6eee1c2

1 file changed

Lines changed: 19 additions & 3 deletions

File tree

cloud/src/LrmCloud.Api/Services/MinioStorageService.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,18 @@ private static string GetObjectName(int projectId, string filePath)
223223
throw new ArgumentException("File path cannot be empty", nameof(filePath));
224224
}
225225

226-
// Normalize path separators first (handle both Windows and Unix paths)
226+
// Security: Decode URL-encoded characters to catch double-encoding attacks
227+
// e.g., %252e%252e -> %2e%2e -> .. (path traversal attempt)
228+
var decodedPath = Uri.UnescapeDataString(filePath);
229+
230+
// Keep decoding until no more changes (handles triple+ encoding)
231+
while (decodedPath != filePath)
232+
{
233+
filePath = decodedPath;
234+
decodedPath = Uri.UnescapeDataString(filePath);
235+
}
236+
237+
// Normalize path separators (handle both Windows and Unix paths)
227238
filePath = filePath.Replace('\\', '/');
228239

229240
// Remove leading slash if present
@@ -236,19 +247,24 @@ private static string GetObjectName(int projectId, string filePath)
236247
var segments = fullPath.Split('/', StringSplitOptions.RemoveEmptyEntries);
237248

238249
// Security: Check for path traversal in ALL segments
239-
// This catches: "..", ".", encoded variants after URL decoding, etc.
240250
foreach (var segment in segments)
241251
{
242252
if (segment == ".." || segment == ".")
243253
{
244254
throw new ArgumentException("Invalid file path: path traversal not allowed", nameof(filePath));
245255
}
246256

247-
// Also check for null bytes or other suspicious characters
257+
// Check for null bytes or other suspicious characters
248258
if (segment.Contains('\0'))
249259
{
250260
throw new ArgumentException("Invalid file path: null bytes not allowed", nameof(filePath));
251261
}
262+
263+
// Check for URL-encoded sequences that shouldn't be in final path
264+
if (segment.Contains('%'))
265+
{
266+
throw new ArgumentException("Invalid file path: encoded characters not allowed", nameof(filePath));
267+
}
252268
}
253269

254270
// Rebuild the clean path from validated segments

0 commit comments

Comments
 (0)