@@ -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